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 in cascade #2107

Closed
alexlamsl opened this issue Jun 15, 2017 · 21 comments · Fixed by #2109
Closed

Bug in cascade #2107

alexlamsl opened this issue Jun 15, 2017 · 21 comments · Fixed by #2109
Labels

Comments

@alexlamsl
Copy link
Collaborator

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

function f0(b) {
    {
        var brake1 = 5;
        while ((c = c + 1) + /[abc4]/.test((a++ || b || 5).toString()) && --brake1 > 0) {
            try {
                {
                    var b = function f1() {
                        {
                            var bar = function f2(arguments) {
                                if (c = 1 + c, ((1 ^ NaN) > (undefined && "number")) >>> "number" % Infinity % (38..toString() % -5)) {
                                    c = 1 + c, a && (a.Infinity = ((-3 ^ Infinity) - {} * "foo") % (3 & 4 | ("undefined" || -3)));
                                } else {
                                    c = 1 + c, "function" <= undefined > (a && (a.b += -2 <= undefined)) >= ((c = c + 1, 
                                    22) <= (4 & Infinity));
                                }
                                {
                                }
                            }([ (c = 1 + c, "foo" - ([ , 0 ].length === 2) !== 0 % true ^ (Infinity, 3) % ([] == 4)) ][(c = c + 1) + -a]);
                        }
                        {
                            var parseInt = function f3() {
                                function f4(NaN, bar) {
                                }
                                var b_2 = f4("function", "function");
                            }(--b + (void function() {
                            }() || 1).toString()[(c = c + 1) + (b + 1 - .1 - .1 - .1)]);
                        }
                    }(a++ + new function() {
                        this.NaN = ((("" ^ -2) <= (a && (a.a = undefined == undefined))) >>> ("foo" + -0 === "object" <= 3) === ("number" === []) * (23..toString() <= -5) * (a && (a[a++ + -0] = ("number" & [ , 0 ][1]) + (false === 0)))) >> (~(23..toString() | /[a2][^e]+$/) >> {} % ([ , 0 ].length === 2) % (25 > "object") || (a && (a[[ (c = 1 + c, 
                        (("undefined" ^ "undefined") & ([ , 0 ].length === 2) >>> 3) << (2 >>> 4 !== ({} ^ -1))), (c = 1 + c, 
                        (c = c + 1, "undefined") > (a && (a[(c = 1 + c, 3 - -5 <= (1 ^ "number") ^ void (a && (a[(c = 1 + c, 
                        a && (a.undefined >>= (a && (a.var += (false == "bar", -3 !== 0))) & (false | 24..toString()) === ("undefined" !== -4)))] |= "number" == false)))] += null & "bar")), 
                        5 != 0 != ("function" && [ , 0 ].length === 2)) ]] += ({} | 0) > (2 || "function"))) !== ((a && (a[(c = 1 + c, 
                        (a && (a[b %= a] >>>= 5 !== "undefined" || "foo" % 5)) + ((a && (a[(c = 1 + c, (23..toString() <= "bar") << Infinity % null ^ (3 % {} || 3 * -5))] = -3 >= "undefined")) < /[a2][^e]+$/ / 3))] = undefined && -0)) !== -4 <= []));
                        this.a += (NaN > /[a2][^e]+$/ > (-0 ^ 4) !== ("object" <= 2) - (a && (a.a >>>= -0 >> 1)) ^ (c = c + 1, 
                        c = c + 1, /[a2][^e]+$/ || {})) << ((5 ^ NaN | null > 1) & -3 % -2 != 1 >> "bar") / (2 + "undefined" && void "object" && ("undefined" >= 3) >>> ([ , 0 ].length === 2 & -3));
                        this[{
                            get Infinity() {
                                c = c + 1;
                                {
                                    return b--;
                                }
                            },
                            "": [ , 0 ].length === 2
                        }] /= ((("function" | -5) << ("function", 0) && "number" > "foo" | (25 | "function")) == ("" + null > 38..toString() * "foo") + (NaN & {}) % (a && (a[(c = 1 + c, 
                        ((c = c + 1, true) >= -5 % "object") >> ((2 & "bar") > NaN + "object"))] += "number" % NaN))) >>> (((-3 <= 0) >>> (0, 
                        [ , 0 ][1]) == (null === 25) >>> (-5 & null)) < (38..toString() < 4 < ("function" !== -3) <= ("object" & 25 ^ (22 | 3))));
                        var undefined_2 = void b, bar_1 = (c = c + 1) + [ (c = 1 + c, (/[a2][^e]+$/ || Infinity) * ("function" ^ []) << (5 - undefined != ("function" && NaN))) ].a;
                        return a++ + (typeof bar_1 == "object");
                        {
                            var brake14 = 5;
                            L202814: while ([ (c = 1 + c, bar_1 && (bar_1.foo = ((/[a2][^e]+$/ | 23..toString()) !== (undefined && 3)) >> (38..toString() << 24..toString()) / ([ , 0 ][1], 
                            -3))), (c = 1 + c, "" !== 25 !== (undefined_2 && (undefined_2.null = "" != 25)) !== (undefined_2 = (c = c + 1, 
                            2) >>> (bar_1 && (bar_1.NaN += 3 >= 4)))), (c = 1 + c, (undefined - [] || 38..toString() === ([ , 0 ].length === 2)) < ({} && null) / ([ , 0 ][1] > 4)), (c = 1 + c, 
                            (NaN >>> undefined | "object" & 22) === (Infinity <= "number" ^ (bar_1 && (bar_1[(c = 1 + c, 
                            (-5 != -4) < (23..toString() | 22) !== (1 * 23..toString() && -4 >> /[a2][^e]+$/))] += 22 / undefined)))) ] && --brake14 > 0) {
                                switch ((c = c + 1) + ((c = 1 + c, (2 % 2 ^ ("bar" | null)) < (3 >> "object" <= (c = c + 1, 
                                [ , 0 ].length === 2))) ? (c = 1 + c, Infinity > 0 > "number" / 2 >= +(undefined & null)) : (c = 1 + c, 
                                (undefined << -5 || "" - -2) < (23..toString() !== 2) + delete 5))) {
                                  case /[abc4]/.test(((c = 1 + c, c = c + 1, [ , 0 ][1] > 3 ^ [] >> null) || b || 5).toString()):
                                    break;

                                  case --b + (c = 1 + c, (-5 && Infinity) ^ /[a2][^e]+$/ === 4 ^ ((false, []) ^ [ , 0 ].length === 2 == 2)):
                                    break;

                                  case +a:
                                    c = 1 + c, c = c + 1, -5 >> 22 | (undefined || Infinity);
                                    break;

                                  default:
                                    c = 1 + c, ("object" * 5 < (-2 < -0)) >> ((Infinity == 3) >>> (NaN >> true));
                                }
                            }
                        }
                    }());
                }
            } catch (b) {
                {
                    var brake18 = 5;
                    do {
                        {
                            ({
                                0: (c = 1 + c, (5 >> "object" ^ (a = -0 <= 3)) !== (3 & 4) % ({} === Infinity)),
                                3: (c = 1 + c, ((3 ^ "object") <= (3 | 1)) * (null * "" == (-0 ^ 25))),
                                foo: (c = 1 + c, (a && (a[/[a2][^e]+$/] = "bar" === 38..toString() == (5 && 24..toString()))) / ("object" !== "foo" | true << -5)),
                                length: (c = 1 + c, (2 !== -1) >= (-0 === "foo") & (a && (a[(c = 1 + c, ((-5 === 38..toString()) > NaN + "foo") >> ((4 == Infinity) >>> (1 !== "number")))] = "function" !== 25)) == (false | -2))
                            })[--b];
                            for (var brake21 = 5; typeof b == "string" && brake21 > 0; --brake21) {}
                            {
                                var brake23 = 5;
                                while (--b + (--b + ~b) && --brake23 > 0) {
                                    switch (a++ + +("bar" + "" > [ , 0 ][1] >>> undefined == (5 << 4) % (/[a2][^e]+$/ % 3))) {
                                      case (c = c + 1) + (c = 1 + c, "number" / "object" * ("" ^ "foo") < (a && (a[--b + ((c = 1 + c, 
                                        (-2 | -3 || a && (a.undefined = "" < 25)) % ((-0 >= -4) >> (4 <= {}))) ? (c = 1 + c, 
                                        (2 <= 0) / (3 ^ 0) == ("number" === -0 !== ("function" && "undefined"))) : (c = 1 + c, 
                                        ((a && (a.null %= "bar" > 3)) >>> (a %= undefined >> 4)) + (([ , 0 ].length === 2) >= [] != -0 / 0)))] += (2 | 0) / ("undefined" && "number")))):
                                        c = 1 + c, (a -= "foo" < 25) >>> "function" + 22 == +(false < -1);
                                        c = 1 + c, ([] && 0) + 5 % "undefined" < (-5 <= 5) + (true - "function");
                                        break;

                                      case a++ + --b:
                                        break;

                                      case c = 1 + c, (a && (a.a &= undefined % -1)) << ("function" && 4) == ("number" ^ -0) % ([ , 0 ][1] + 3):
                                        break;

                                      case --b + !((-5 != -2 === (a %= undefined ^ 23..toString())) % (a += (-4 >= -4) * (-4 ^ "undefined"))):
                                        c = 1 + c, (NaN % null & ("object" ^ 0)) / (/[a2][^e]+$/ % 24..toString() <= (/[a2][^e]+$/ < /[a2][^e]+$/));
                                        c = 1 + c, ("undefined" << false) + (38..toString() == 0) && (null >>> undefined) + -3 % NaN;
                                        break;
                                    }
                                }
                            }
                            var a;
                        }
                    } while (--b + !(a && (a.c = ((3, 0) | (c = c + 1, [ , 0 ].length === 2)) >>> (c = c + 1, 
                    a && (a[(c = 1 + c, (-1 >= -3 & (-1 | "foo")) * (4 <= "undefined" ^ (a && (a.NaN += [ , 0 ].length === 2 & 3))))] = [ , 0 ][1] ^ false)))) && --brake18 > 0);
                }
                switch (b -= a) {
                  default:
                    typeof ((c = c + 1) + (b = a));
                    {
                        var brake32 = 5;
                        while ((c = c + 1) + ({
                            c: (c = 1 + c, (c = c + 1, [ , 0 ][1] << 3) === (true !== -3) * (true >>> 2)),
                            undefined: (c = 1 + c, (a && (a.var &= 25 < 1 != (22 || [ , 0 ][1]))) - (("number" === ([ , 0 ].length === 2)) + -4 * -4))
                        }.foo || 9).toString()[a && a.b] && --brake32 > 0) {
                            void ((24..toString() === true) >> (-5 | "bar") << ((1 == true) < 5 % /[a2][^e]+$/));
                        }
                    }

                  case a++ + false:
                    {
                        var brake34 = 5;
                        while (--b + typeof ((c = c + 1) + a--) && --brake34 > 0) {
                            var expr35 = {
                                "": (c = 1 + c, ((38..toString() ^ 25) > undefined % true) * ((arguments_1 && (arguments_1[(c = 1 + c, 
                                (-3 < [] ^ {} >>> [ , 0 ][1]) >= +~38..toString())] = 0 >> Infinity)) >> (arguments_1 && (arguments_1[(c = 1 + c, 
                                (c = c + 1, /[a2][^e]+$/) << ("foo" >= 1) <= (([] | Infinity) <= (-5 & "number")))] += -5 == 3))))
                            };
                            L202815: for (var key35 in expr35) {
                                c = 1 + c;
                                var arguments_1 = expr35[key35];
                                for (var brake36 = 5; (c = c + 1) + -a && brake36 > 0; --brake36) {
                                    switch (c = 1 + c, (3 & "" ^ !undefined) * ([ , 0 ][1] % 0 && (arguments_1 && (arguments_1[(c = 1 + c, 
                                    ((c = c + 1, /[a2][^e]+$/) < (arguments_1 && (arguments_1.var += 1 + false))) + (0 >= ([ , 0 ].length === 2) === (5 || -5)))] /= -3 & undefined)))) {
                                      case c = 1 + c, ([ , 0 ][1] || 2) >= (22 || undefined) && ("number" !== "foo") <= true % 38..toString():
                                        ;
                                        break;

                                      case c = 1 + c, c = c + 1, 1 <= -4 ^ (2 ^ 24..toString()):
                                        ;
                                        break;

                                      default:
                                        ;

                                      case c = 1 + c, arguments_1 && (arguments_1[!a] *= (true | "object") >> (-4 >>> null) === (1 == -1) % (/[a2][^e]+$/ >> "foo")):
                                        ;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    {
                        var brake38 = 5;
                        L202816: while (a++ + ((Infinity / -5 && 23..toString() >= 4) & (-0 != "" && ("foo" && "object"))) && --brake38 > 0) {
                            ++a;
                        }
                    }
                    break;

                  case (c = c + 1) + (b = a):
                    {
                        var expr40 = a++ + /[abc4]/.test((--b + {
                            NaN: (c = 1 + c, (2 || "object") >> (null >= ([ , 0 ].length === 2)), -5 > 3 <= ("function" ^ -0)),
                            NaN: (c = 1 + c, {} - Infinity === {} + "bar" !== (null && -2) > ("foo" <= 3)),
                            in: (c = 1 + c, (Infinity_2 && (Infinity_2[(c = 1 + c, Infinity + {} != null * -5 ^ (-0 * false | (5 || [ , 0 ][1])))] += 5 > 3)) << (23..toString() << -2) || [] >>> 3 && 25 == /[a2][^e]+$/),
                            1.5: (c = 1 + c, ((true && false) >>> ([] & -2)) + void (NaN, -2)),
                            "\t": (c = 1 + c, c = c + 1, [] + "object" >= -3 - -4)
                        }.b || b || 5).toString());
                        for (var key40 in expr40) {
                            c = 1 + c;
                            var Infinity_2 = expr40[key40];
                            switch ((c = c + 1) + ((b += a) ? 22 : a++ + ((!"bar" && ("foo", -5)) << ((undefined || 1) > (-0 || "function"))))) {
                              case -b:
                                {
                                    var brake42 = 5;
                                    while ((c = 1 + c, "object" === 5 ^ 24..toString() > 0 ^ (/[a2][^e]+$/ > "undefined" && -3 ^ undefined)) && --brake42 > 0) {
                                        c = 1 + c, (Infinity_2 && (Infinity_2.in = -1 !== -0 === 4 << undefined)) !== (Infinity_2 && (Infinity_2.foo = delete true ^ "undefined" <= "undefined"));
                                    }
                                }
                                if (c = 1 + c, ((25 == NaN) >>> ([] && 38..toString())) - (Infinity / -3 > "function" >>> 22)) {
                                    c = 1 + c, arguments_1 && (arguments_1[a++ + [ (c = 1 + c, (5 ^ "number") >> (-0 ^ 1) & "number" % 22 > (2 > 25)), (c = 1 + c, 
                                    (24..toString() !== 1) >>> ("object" >>> [ , 0 ][1]) <= (22 >= -3 < (arguments_1 += "undefined" ^ false))), (c = 1 + c, 
                                    c = c + 1, (Infinity_2 && (Infinity_2.Infinity = "undefined" & "bar")) - -4 * -4), (c = 1 + c, 
                                    arguments_1 && (arguments_1.null += (-3, [ , 0 ][1]) | -5 ^ [] || ({} && 2, -4 << -2))), (c = 1 + c, 
                                    (Infinity_2 = "bar" === -1) < (3 >= 38..toString()), /[a2][^e]+$/ > "foo" ^ -2 % 3) ]] *= (1 >= Infinity) >>> ("object" & []) >> ((Infinity_2 = false & NaN) << (24..toString() === NaN)));
                                } else {
                                    c = 1 + c, c = c + 1, (3 && 38..toString()) ^ ([ , 0 ].length === 2) > -0;
                                }
                                break;

                              case --b + [ (c = 1 + c, ([ , 0 ].length === 2 & null ^ /[a2][^e]+$/ & "bar") >>> (arguments_1 && (arguments_1[--b + --b] += -0 <= 1 & "" >>> -0))) ][(c = c + 1) + ({} >>> "object", 
                                [] >> 24..toString()) / (0 != "number" && [] <= 25)]:
                                {
                                    var brake47 = 5;
                                    while ((c = 1 + c, ("foo", 1) + (23..toString() != false) & ("undefined" || -3) >= 4 >>> "bar") && --brake47 > 0) {
                                        c = 1 + c, (-0 << 4) / (24..toString() | -1) >>> (25 * -4 != ([ , 0 ].length === 2) <= 4);
                                    }
                                }
                                break;

                              case a++:
                                try {
                                    c = 1 + c, c = c + 1, (c = c + 1, 25) === 22 >>> ([ , 0 ].length === 2);
                                } catch (b) {
                                }
                                {
                                    var expr51 = (c = 1 + c, Infinity_2 = (-1 >= 25) % (-5 + Infinity) & (Infinity_2 += [] <= "foo") !== true << 4);
                                    for (var key51 in expr51) {
                                        c = 1 + c;
                                        var undefined_1 = expr51[key51];
                                        c = 1 + c, (null && -2) < (c = c + 1, "object") || (Infinity_2 += "undefined" + 23..toString() >>> 4 - "bar");
                                    }
                                }
                                break;

                              default:
                                for (var brake53 = 5; (c = 1 + c, (undefined * 24..toString() !== "object" + "foo") - ([ , 0 ][1] >> -1 ^ ([ , 0 ][1] ^ [ , 0 ][1]))) && brake53 > 0; --brake53) {
                                    c = 1 + c, (24..toString() + 3 !== ("function" && 24..toString())) * ("foo" << -4 >>> (Infinity_2 = ([], 
                                    "function")));
                                }
                                try {
                                    c = 1 + c, undefined_1 = (!-3 & 38..toString() / "object") !== (Infinity_2 && (Infinity_2.c = NaN !== -0 & "object" != NaN));
                                } finally {
                                }
                            }
                        }
                    }
                    break;

                  case --b + (1 === 1 ? a : b) ? a++ + a++ : delete a:
                    {
                        var brake57 = 5;
                        while (a-- && --brake57 > 0) {
                            try {
                                c = 1 + c, (arguments_1 && (arguments_1[(c = 1 + c, ((3 || "bar") > ("number" === -2)) >> (("number" ^ "function") >= (38..toString() || 24..toString())))] >>>= -0 == "")) < (0 < undefined) && undefined / 23..toString() > (-3 ^ 25);
                            } catch (a_2) {
                            } finally {
                            }
                            c = c + 1;
                            c = 1 + c, (Infinity_2 = (-3, /[a2][^e]+$/)) - (undefined_1 && (undefined_1[(c = 1 + c, 
                            ~((0 !== -2) < {} << 1))] = 5 ^ true)) === ("object" !== -4 & ("bar" & "object"));
                        }
                    }
                    {
                        var expr63 = "object";
                        for (var key63 in expr63) {
                            c = 1 + c;
                            var a_2 = expr63[key63];
                            {
                                var NaN_2 = function f5(b_1) {
                                    c = 1 + c, ({} >= 23..toString(), 2 | -0) % ((NaN !== {}) * (3 < -0));
                                    c = 1 + c, (2 << -2 || (c = c + 1, 22)) >> (b_1 && (b_1[delete (a_2 /= [ , 0 ][1] || -1) === (false << NaN && {} > -1)] ^= 25 ^ [ , 0 ].length === 2 || "" << -0));
                                }(a++ + b--);
                            }
                        }
                    }
                    break;
                }
            }
        }
    }
    if ((arguments_1 && (arguments_1.in = (0 === true) + (4 === undefined))) === (Infinity ^ [ , 0 ][1], 
    "function" > -4)) {
        var brake68 = 5;
        do {
        } while ((0 === 1 ? a : b) && --brake68 > 0);
    }
}

var b = f0();

console.log(null, a, b, c);
// uglified code
// (beautified)
function f0(b) {
    for (var brake1 = 5; (c += 1) + /[abc4]/.test((a++ || b || 5).toString()) && --brake1 > 0; ) {
        try {
            var b = function() {
                (function(arguments) {
                    c = 1 + c, !1 >>> NaN % (38..toString() % -5) ? (c = 1 + c, a && (a.Infinity = (-3 - "foo" * {}) % 0)) : (c = 1 + c, 
                    a && (a.b += !1), c += 1);
                })((c = 1 + c, c += 1)), --b, 1..toString()[(c += 1) + (b + 1 - .1 - .1 - .1)];
            }((a++, new function() {
                this.NaN = ((-2 <= (a && (a.a = !0))) >>> !1 == ("number" === []) * (23..toString() <= -5) * (a && (a[a++ - 0] = ("number" & [ , 0 ][1]) + !1))) >> (~(23..toString() | /[a2][^e]+$/) >> {} % (2 === [ , 0 ].length) % !1 || (a && (a[[ (c = 1 + c, 
                (0 & (2 === [ , 0 ].length) >>> 3) << (0 != (-1 ^ {}))), (c = 1 + c, c += 1, a && (a[(c = 1 + c, 
                !1 ^ void (a && (a[(c = 1 + c, a && (a.undefined >>= (a && (a.var += !0)) & !0 === (!1 | 24..toString())))] |= !1)))] += 0), 
                1 != (2 === [ , 0 ].length)) ]] += (0 | {}) > 2)) !== ((a && (a[(c = 1 + c, (a && (a[b %= a] >>>= !0)) + ((a && (a[(c = 1 + c, 
                (23..toString() <= "bar") << NaN ^ (3 % {} || -15))] = !1)) < NaN))] = void 0)) !== -4 <= [])), 
                this.a += (!1 !== !1 - (a && (a.a >>>= 0)) ^ (c += 1, c += 1, /[a2][^e]+$/)) << NaN, 
                this[{
                    get Infinity() {
                        return c += 1, b--;
                    },
                    "": 2 === [ , 0 ].length
                }] /= (25 == ("null" > "foo" * 38..toString()) + (NaN & {}) % (a && (a[(c = 1 + c, 
                c += 1, 0)] += NaN))) >>> ((!0 >>> [ , 0 ][1] == 0) < (38..toString() < 4 < !0 <= 23));
                c += 1, c = 1 + (c += 1);
                a++;
            }()));
        } catch (b) {
            var brake18 = 5;
            do {
                c = 1 + (c = 1 + (c = 1 + c)), (a = !0) && (a[/[a2][^e]+$/] = "bar" === 38..toString() == 24..toString()), 
                c = 1 + c, a && (a[(c = 1 + c, ((-5 === 38..toString()) > "NaNfoo") >> 0)] = !0), 
                --b;
                for (var brake21 = 5; "string" == typeof b && brake21 > 0; --brake21) {}
                for (var brake23 = 5; --b + (--b + ~b) && --brake23 > 0; ) {
                    switch (a++ + +("bar" > [ , 0 ][1] >>> void 0 == NaN)) {
                      case (c += 1) + (c = 1 + c, NaN < (a && (a[--b + (c = 1 + c, -1 % (!0 >> (4 <= {})) ? (c = 1 + c, 
                        !1) : (c = 1 + c, ((a && (a.null %= !1)) >>> (a %= 0)) + ((2 === [ , 0 ].length) >= [] != NaN)))] += NaN))):
                        a -= !1, c = 1 + (c = 1 + c);
                        break;

                      case a++ + --b:
                      case c = 1 + c, (a && (a.a &= NaN)) << 4 == 0 % ([ , 0 ][1] + 3):
                        break;

                      case --b + !((!0 === (a %= void 0 ^ 23..toString())) % (a += -4)):
                        c = 1 + c, 24..toString(), c = 1 + c, 38..toString();
                    }
                }
                var a;
            } while (--b + !(a && (a.c = (0 | (c += 1, 2 === [ , 0 ].length)) >>> (c += 1, a && (a[(c = 1 + c, 
            1 * (!1 ^ (a && (a.NaN += 2 === [ , 0 ].length & 3))))] = !1 ^ [ , 0 ][1])))) && --brake18 > 0);
            switch (b -= a) {
              default:
                c += 1, b = a;
                for (var brake32 = 5; (c += 1) + ({
                    c: (c = 1 + c, 0 == (c += 1, [ , 0 ][1] << 3)),
                    undefined: (c = 1 + c, (a && (a.var &= !0)) - (("number" === (2 === [ , 0 ].length)) + 16))
                }.foo || 9).toString()[a && a.b] && --brake32 > 0; ) {
                    24..toString();
                }

              case a++ + !1:
                for (var brake34 = 5; --b + typeof ((c += 1) + a--) && --brake34 > 0; ) {
                    var expr35 = {
                        "": (c = 1 + c, ((25 ^ 38..toString()) > NaN) * ((arguments_1 && (arguments_1[(c = 1 + c, 
                        (-3 < [] ^ {} >>> [ , 0 ][1]) >= +~38..toString())] = 0)) >> (arguments_1 && (arguments_1[(c = 1 + c, 
                        c += 1, 0 <= (([] | 1 / 0) <= 0))] += !1))))
                    };
                    for (var key35 in expr35) {
                        c = 1 + c;
                        for (var arguments_1 = expr35[key35], brake36 = 5; (c += 1) + -a && brake36 > 0; --brake36) {
                            switch (c = 1 + c, 1 * ([ , 0 ][1] % 0 && arguments_1 && (arguments_1[(c = 1 + c, 
                            c += 1, (/[a2][^e]+$/ < (arguments_1 && (arguments_1.var += 1))) + (0 >= (2 === [ , 0 ].length) === 5))] /= 0))) {
                              case c = 1 + c, ([ , 0 ][1] || 2) >= 22 && !0 <= !0 % 38..toString():
                              case c = 1 + c, c += 1, 2 ^ 24..toString():
                                break;

                              default:
                              case c = 1 + c, arguments_1 && (arguments_1[!a] *= !1):
                            }
                        }
                    }
                }
                for (var brake38 = 5; a++ + (23..toString() >= 4 & !1) && --brake38 > 0; ) {
                    ++a;
                }
                break;

              case (c += 1) + (b = a):
                var expr40 = a++ + /[abc4]/.test((--b + {
                    NaN: (c = 1 + c, !0),
                    NaN: (c = 1 + c, {} - 1 / 0 === {} + "bar" != !1),
                    in: (c = 1 + c, (Infinity_2 && (Infinity_2[(c = 1 + c, 1 / 0 + {} != -0 ^ 5)] += !0)) << (23..toString() << -2) || [] >>> 3 && !1),
                    1.5: (c = 1 + c, (!1 >>> (-2 & [])) + void 0),
                    "\t": (c = 1 + c, c += 1, [] + "object" >= 1)
                }.b || b || 5).toString());
                for (var key40 in expr40) {
                    c = 1 + c;
                    var Infinity_2 = expr40[key40];
                    switch ((c += 1) + ((b += a) ? 22 : 0 + a++)) {
                      case -b:
                        for (var brake42 = 5; c = 1 + c, !1 ^ 24..toString() > 0 ^ !1 && --brake42 > 0; ) {
                            c = 1 + c, Infinity_2 && (Infinity_2.in = !1), Infinity_2 && (Infinity_2.foo = 0);
                        }
                        c = 1 + c, (!1 >>> ([] && 38..toString())) - !1 ? (c = 1 + c, arguments_1 && (arguments_1[a++ + [ (c = 1 + c, 
                        0), (c = 1 + c, (1 !== 24..toString()) >>> ("object" >>> [ , 0 ][1]) <= (!0 < (arguments_1 += 0))), (c = 1 + c, 
                        c += 1, (Infinity_2 && (Infinity_2.Infinity = 0)) - 16), (c = 1 + c, arguments_1 && (arguments_1.null += [ , 0 ][1] | -5 ^ [] || 0)), (c = 1 + c, 
                        Infinity_2 = !1, 38..toString(), -2) ]] *= !1 >>> ("object" & []) >> ((Infinity_2 = 0) << (NaN === 24..toString())))) : (c = 1 + c, 
                        c += 1, 38..toString());
                        break;

                      case --b + [ (c = 1 + c, (2 === [ , 0 ].length & null ^ 0) >>> (arguments_1 && (arguments_1[--b + --b] += 0))) ][(c += 1) + ([] >> 24..toString()) / ([] <= 25)]:
                        for (var brake47 = 5; c = 1 + c, 1 + (0 != 23..toString()) & !1 && --brake47 > 0; ) {
                            c = 1 + c, 24..toString();
                        }
                        break;

                      case a++:
                        try {
                            c = 1 + c, c += 1, c += 1;
                        } catch (b) {}
                        var expr51 = (c = 1 + c, Infinity_2 = 0 & 16 !== (Infinity_2 += [] <= "foo"));
                        for (var key51 in expr51) {
                            c = 1 + c;
                            var undefined_1 = expr51[key51];
                            c = 1 + c, null < (c += 1, "object") || (Infinity_2 += "undefined" + 23..toString() >>> NaN);
                        }
                        break;

                      default:
                        for (var brake53 = 5; c = 1 + c, (void 0 * 24..toString() !== "objectfoo") - ([ , 0 ][1] >> -1 ^ [ , 0 ][1] ^ [ , 0 ][1]) && brake53 > 0; --brake53) {
                            c = 1 + c, 24..toString(), 24..toString(), Infinity_2 = "function";
                        }
                        try {
                            c = 1 + c, undefined_1 = (!1 & 38..toString() / "object") !== (Infinity_2 && (Infinity_2.c = 1));
                        } finally {}
                    }
                }
                break;

              case --b + a ? a++ + a++ : delete a:
                for (var brake57 = 5; a-- && --brake57 > 0; ) {
                    try {
                        c = 1 + c, (arguments_1 && (arguments_1[(c = 1 + c, !0 >> (0 >= (38..toString() || 24..toString())))] >>>= !0)) < !1 && 23..toString();
                    } catch (a_2) {}
                    c = 1 + (c += 1), Infinity_2 = /[a2][^e]+$/, undefined_1 && (undefined_1[(c = 1 + c, 
                    ~(!0 < {} << 1))] = 4);
                }
                for (var key63 in "object") {
                    c = 1 + c;
                    var a_2 = "object"[key63];
                    (function(b_1) {
                        c = 1 + c, 23..toString(), c = 1 + c, b_1 && (b_1[0 === (a_2 /= [ , 0 ][1] || -1, 
                        !0)] ^= 25 ^ 2 === [ , 0 ].length || 0);
                    })(a++ + b--);
                }
            }
        }
    }
    if (!1 === (arguments_1 && (arguments_1.in = 0))) {
        var brake68 = 5;
        do {} while (b && --brake68 > 0);
    }
}

var a = 100, b = 10, c = 0, b = f0();

console.log(null, a, b, c);
original result:
null 100 undefined 45

uglified result:
null 100 undefined 49

minify(options):
{
  "mangle": false
}

Suspicious compress options:
  cascade
  collapse_vars
  dead_code
  inline
  join_vars
  sequences
  side_effects
  unused
@alexlamsl
Copy link
Collaborator Author

alexlamsl commented Jun 15, 2017

So far narrowed down to:

var a = 100, b = 10, c = 0;

function f0(b) {
    var b = function f1() {
        {
            var bar = function f2(arguments) {
                if (c = 1 + c, ((1 ^ NaN) > (undefined && "number")) >>> "number" % Infinity % (38..toString() % -5)) {
                    c = 1 + c, a && (a.Infinity = ((-3 ^ Infinity) - {} * "foo") % (3 & 4 | ("undefined" || -3)));
                }
            }([ (c = 1 + c, "foo" - ([ , 0 ].length === 2) !== 0 % true ^ (Infinity, 3) % ([] == 4)) ][(c = c + 1) + -a]);
        }
    }(a++ + new function() {
        this.NaN = ((("" ^ -2) <= (a && (a.a = undefined == undefined))) >>> ("foo" + -0 === "object" <= 3) === ("number" === []) * (23..toString() <= -5) * (a && (a[a++ + -0] = ("number" & [ , 0 ][1]) + (false === 0)))) >> (~(23..toString() | /[a2][^e]+$/) >> {} % ([ , 0 ].length === 2) % (25 > "object") || (a && (a[[ (c = 1 + c,
        (("undefined" ^ "undefined") & ([ , 0 ].length === 2) >>> 3) << (2 >>> 4 !== ({} ^ -1))), (c = 1 + c,
        (c = c + 1, "undefined") > (a && (a[(c = 1 + c, 3 - -5 <= (1 ^ "number") ^ void (a && (a[(c = 1 + c,
        a && (a.undefined >>= (a && (a.var += (false == "bar", -3 !== 0))) & (false | 24..toString()) === ("undefined" !== -4)))] |= "number" == false)))] += null & "bar")),
        5 != 0 != ("function" && [ , 0 ].length === 2)) ]] += ({} | 0) > (2 || "function"))) !== ((a && (a[(c = 1 + c,
        (a && (a[b %= a] >>>= 5 !== "undefined" || "foo" % 5)) + ((a && (a[(c = 1 + c, (23..toString() <= "bar") << Infinity % null ^ (3 % {} || 3 * -5))] = -3 >= "undefined")) < /[a2][^e]+$/ / 3))] = undefined && -0)) !== -4 <= []));
        this.a += (NaN > /[a2][^e]+$/ > (-0 ^ 4) !== ("object" <= 2) - (a && (a.a >>>= -0 >> 1)) ^ (c = c + 1,
        c = c + 1, /[a2][^e]+$/ || {})) << ((5 ^ NaN | null > 1) & -3 % -2 != 1 >> "bar") / (2 + "undefined" && void "object" && ("undefined" >= 3) >>> ([ , 0 ].length === 2 & -3));
        var undefined_2 = void b, bar_1 = (c = c + 1) + [ (c = 1 + c, (/[a2][^e]+$/ || Infinity) * ("function" ^ []) << (5 - undefined != ("function" && NaN))) ].a;
        return a++ + (typeof bar_1 == "object");
    }());
}

var b = f0();

console.log(null, a, b, c);
$ uglifyjs test.js -b bracketize -c cascade=0 -o good.js
$ uglifyjs test.js -b bracketize -c cascade=1 -o bad.js
$ cat test.js | node
null 103 undefined 7
$ cat good.js | node
null 103 undefined 7
$ cat bad.js | node
null 103 undefined 8
--- a/good.js
+++ b/bad.js
@@ -10,7 +10,7 @@ function f0(b) {
         1 != (2 === [ , 0 ].length)) ]] += (0 | {}) > 2)) !== ((a && (a[(c = 1 + c, (a && (a[b %= a] >>>= !0)) + ((a && (a[(c = 1 + c,
         (23..toString() <= "bar") << NaN ^ (3 % {} || -15))] = !1)) < NaN))] = void 0)) !== -4 <= [])),
         this.a += (!1 !== !1 - (a && (a.a >>>= 0)) ^ (c += 1, c += 1, /[a2][^e]+$/)) << NaN;
-        var bar_1 = (c += 1) + [ (c = 1 + c, /[a2][^e]+$/ * ("function" ^ []) << !0) ].a;
+        c += 1, c = 1 + (c += 1);
         a++;
     }()));
 }

OT: off for a nap 💤

@alexlamsl alexlamsl added the bug label Jun 15, 2017
@alexlamsl
Copy link
Collaborator Author

This seems to be the bare minimum - and it looks like collapse_vars is at fault instead:

var c = 0;

!function() {
    c++;
}(c++ + new function() {
    this.NaN = 0;
    var bar_1 = (c = c + 1) + (c = 1 + c);
    return c++ + bar_1;
}());

console.log(c);

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

The regression is pretty recent:

$ cat 2107.js | node
5
$ git checkout v3.0.16
HEAD is now at 4231f73... v3.0.16
$ cat 2107.js | bin/uglifyjs -c | node
5
$ git checkout v3.0.17
HEAD is now at 57dc4fb... v3.0.17
$ cat 2107.js | bin/uglifyjs -c | node
6

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

Regression introduced in b85a358

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

looks like collapse_vars is at fault instead

I think cascade remains the underlying cause:

$ cat 2107.js | node
5
$ cat 2107.js | bin/uglifyjs -c cascade=0,reduce_vars=0,collapse_vars=1 | node
5
$ cat 2107.js | bin/uglifyjs -c cascade=1,reduce_vars=0,collapse_vars=1 | node
6

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

I think any changes to lib/*.js would benefit from 1M iterations of test/ufuzz.js before release. The compress code in particular is a fairly complex to say the least.

@alexlamsl
Copy link
Collaborator Author

I think any changes to lib/*.js would benefit from 1M iterations of test/ufuzz.js before release.

There were >1MFuzz in between those releases, mind you 😅

@alexlamsl
Copy link
Collaborator Author

Regression introduced in b85a358

Interesting - that commit doesn't look related to the test code. Thanks for the information anyway 👍

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

There were >1MFuzz in between those releases, mind you

My apologies and 👍 .

@alexlamsl
Copy link
Collaborator Author

I think the general phenomema is that inline is now shaking out a lot of potential bugs in the existing code. Though a lot of them seems to be related to AST node cloning, which are somewhat hard to nail as they are very delicately linked to runtime performance.

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

That makes sense.

In fairness, I did not anticipate function cloning when I wrote collapse_vars. The algorithm depended on the fact that it was replacing single-use variables and just stealing the AST value from the declaration definition as there was no chance of sharing the variable value at the time - the variable reference count must be exactly 1. I suppose the definition value could always be deep cloned when collapsed, but performance could take a hit.

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

that commit doesn't look related to the test code.

That's why it's so curious that it affects it. You can double check it yourself.

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

there was no chance of sharing the variable value at the time - the variable reference count must be exactly 1.

When a function is deep cloned are variable definition references updated accordingly?

@alexlamsl
Copy link
Collaborator Author

That's why it's so curious that it affects it. You can double check it yourself.

It's due to this.NaN = 0; in #2107 (comment) suppressing the inlining, which in turn exposes a multiple reference issue in the AST, i.e. two instance of (c = c + 1), (c = 1 + c) share the same instance of (c = 1 + c), so when one gets optimised into c = 1 + (c += 1), the other instance got corrupted.

The inline suppression is also incorrect, but that would only produce sub-optimal rather than invalid output.

@alexlamsl
Copy link
Collaborator Author

When a function is deep cloned are variable definition references updated accordingly?

Only label references are updated at the moment.

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

I think collapse_vars' assumption of dealing with variable definitions with ref counts of exactly 1 still holds true - does it not?

@alexlamsl
Copy link
Collaborator Author

I think collapse_vars' assumption of dealing with variable definitions with ref counts of exactly 1 still holds true - does it not?

It does.

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

It's due to this.NaN = 0; in #2107 (comment) suppressing the inlining, which in turn exposes a multiple reference issue in the AST, i.e. two instance of (c = c + 1), (c = 1 + c) share the same instance of (c = 1 + c), so when one gets optimised into c = 1 + (c += 1), the other instance got corrupted.

Trying to understand the issue - is a function clone taking place - and the clone is modified - even though the clone is not ultimately used?

alexlamsl added a commit to alexlamsl/UglifyJS that referenced this issue Jun 16, 2017
@alexlamsl
Copy link
Collaborator Author

alexlamsl commented Jun 16, 2017

Trying to understand the issue - is a function clone taking place - and the clone is modified - even though the clone is not ultimately used?

Yup - and the clone went through optimisation separately before being discarded.

OT: sorry for the late replies - GitHub notification seems to be malfunctioning for the past couple of days.

@kzc
Copy link
Contributor

kzc commented Jun 16, 2017

Yup - and the clone went through optimisation separately before being discarded.

Is this a best_of sort of situation?

@alexlamsl
Copy link
Collaborator Author

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