Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0() {
    function f1() {
        const a_2 = (c = c + 1) + (b ||= a);
        (c = c + 1) + (a++ + delete ("b" * "b" >>> "b" - 25 >>> (("a" || -3) != 5 < null)) || 6).toString()[typeof a_2 == "function" && --_calls_ >= 0 && a_2((c = 1 + c, 
        ((a_2 && (a_2.Infinity = 2 ^ !0o644n)) | this >> Infinity) == (a_2 && (a_2[typeof (c = 1 + c, 
        2 % [] >>> -[ , 0 ][1] ?? (/[a2][^e]+$/ === true) - ("foo" == /[a2][^e]+$/))] += (-3 | "bar") != (c = c + 1, 
        24..toString())))))];
        {
            return --b + typeof foo_2;
        }
    }
    var a = f1(..."" + a, (c = c + 1) + ((~1 && "a" != 23..toString()) < (c = c + 1, 
    "b") + (a && (a.undefined = /[a2][^e]+$/ !== "b"))));
    function f2(bar_1) {
        return;
        {
            var brake4 = 5;
            while ((c = c + 1) + (("object" - 24..toString(), /[a2][^e]+$/ ^ /[a2][^e]+$/) & (a && (a[c = 1 + c, 
            +Infinity < (-4 != false) & (-3 != 4) << (Infinity != false)] = true < "function") && ("b" || [ , 0 ].length === 2)) || a || 3).toString() && --brake4 > 0) {
                switch (a++ + (38..toString() * "b" + (a && (a[c = 1 + c, (bar_1 && (bar_1.async += [ , 0 ][1] == -0)) >> (Number(0xdeadn << 16n | 0xbeefn) == 22), 
                ("undefined" != true) << ("undefined" >>> "foo")] -= [ , 0 ].length === 2 && 3)) >= ((22 ^ [ 3n ][0] > 2) != "undefined" >>> "a"))) {
                  default:
                  case new function a_2(b) {
                        this[/[abc4]/.test(((c = 1 + c, bar_1 && (bar_1[(c = c + 1) + b--] += ("function" % "object" && "" != true) >>> ((bar_1 && (bar_1[c = 1 + c, 
                        (0 >>> false || ("", -4)) | (-3 == "c") >= (4 || 25)] ^= -3 / false)) >>> ([] === -5)))) || b || 5).toString())] = (38..toString() || [ , 0 ].length === 2) / ("c" >>> 22);
                        c = 1 + c, ("" + "" >= 24..toString() >> 2) - (([] === []) >>> ("" << "b"));
                    }("foo", Infinity, (c = 1 + c, (null === 25) % (Infinity * this) === (a && (a.b = {} - 25) && -"foo"))):
                    c = c + 1;
                    break;

                  case --b + -4:
                  case a++ + (bar_1 && bar_1[[ ...[ ...[ ..."" + bar_1, (c = 1 + c, (22 / 1 ^ "object" & true) + (-0 < 1) / ({} + -0)) ], (c = 1 + c, 
                    (-1 === 24..toString()) % void {} % ((23..toString() >= [ , 0 ][1]) % (bar_1 && ({
                        3: bar_1.value
                    } = {
                        3: /[a2][^e]+$/ >= "c"
                    })))), (c = 1 + c, ((a && (a.static += [ , 0 ][1] && "a")) != (-2 & {})) - (1 / -2, 
                    0 <= "b")) ], (c = 1 + c, (null & "b") + ("foo" & -2) ^ (25 - undefined ^ "foo" !== 4)), (c = 1 + c, 
                    ((a && (a.async = true >> 1)) <= (-2 ?? this)) % ((a = 5 != 2) / (c = c + 1, ""))), (c = 1 + c, 
                    ("bar" || -2) <= (23..toString() != "foo") != (a && ([ a.a ] = [ (1 > 5) >>> (-4 ^ /[a2][^e]+$/) ]))), (c = 1 + c, 
                    a = (2 + 1 | (38..toString() && -4)) >= (5 - 3 & (bar_1 += true <= ""))) ]]):
                    break;
                }
            }
        }
    }
    var b_2 = f2();
    function f3(b_1, await, a_2) {
        return --b + (0 === 1 ? a : b);
    }
    var a_1 = f3(typeof f1 == "function" && --_calls_ >= 0 && f1(), "a", --b + ~(((2 || "object") >>> ("a" ^ "function")) - ("bar" >>> this < (-0 == 25))));
    function f4(b_1, []) {
        function f5() {
            switch (c = 1 + c, -0 % 1 >> ("c" > 3) ^ ((true | -3) ^ 5 % 24..toString())) {
              case c = 1 + c, ([] - 1 == (24..toString() && /[a2][^e]+$/)) % (a && (a.in ^= "" * "function" >> (b_1 && (b_1[c = 1 + c, 
                24..toString() != 24..toString() | ("foo" && 1) ?? ([ , 0 ].length === 2) * 38..toString() - (a && (a[c = 1 + c, 
                -1 % 4 - (a && (a[c = 1 + c, ((NaN <= {}) >> (/[a2][^e]+$/ ^ [])) / ((25, "b") & 25 == "undefined")] *= -4 > "object")) != ("foo" | 25) >>> (undefined == "object")] += 38..toString() >= ""))] ||= "b" >>> "foo")))):
                ;
                break;

              case c = 1 + c, (("object" === 23..toString()) + (a && (a[c = 1 + c, (true >> -1, 
                {} > null) % (("bar" == 23..toString()) % (true != ""))] %= [ , 0 ][1] || 3))) / ~(-4 >> "foo"):
                ;
                break;

              case c = 1 + c, ("object" * "undefined" <= (5 !== NaN)) + (a && (a[--b + {
                    ...(c = 1 + c, (c = c + 1, 25) >> "object" - "" > ([ , 0 ][1] !== "object") / (2 >> "a"))
                }] = 23..toString() >>> "c" ^ [ , 0 ][1] >= "c")):
                ;
                break;

              case c = 1 + c, ~("bar" % "" / ("number" == 2)):
                ;
                break;
            }
            {
            }
        }
        var let_1 = f5(-2 in {
            0: (c = 1 + c, ((null && "object") ?? 2 <= 24..toString()) ^ (38..toString() >>> 2 ^ ~"a")),
            in: (c = 1 + c, b_2 = ((-2 | -3) === 4 - "object") - (([] === "c") + (-4 != 23..toString()))),
            get: (c = 1 + c, (a_1 && (a_1[c = 1 + c, (("c" || Infinity) ^ 23..toString() / Infinity) - (3 >>> -3 || [] !== 4)] %= (/[a2][^e]+$/, 
            "b"))) > (b_1 && ({
                0: b_1[c = 1 + c, (-1 < -4) % (4 / [ , 0 ][1]) == (-3 !== 2 === ([ , 0 ][1] ^ -0))]
            } = {
                0: "object" * 2
            })) & 1 >= "" != null <= {}),
            ...let_1,
            get: (c = 1 + c, ((a && ([ a[c = 1 + c, void (("object" >= NaN) + ("" < 38..toString()))] ] = [ "undefined" >>> false ])) & 0 * 5) > (a = "c" << -4 < 0 / true))
        }, [ , 0 ].length === 2);
        function f6(bar_1, foo_1) {
            {
                var expr12 = (c = 1 + c, (0 - false < -0 >>> true) << ("function" >> 24..toString() != (bar_1 && (bar_1.done += NaN != "undefined"))));
                for (var key12 in expr12) {
                    c = 1 + c;
                    var NaN_1 = expr12[key12];
                    c = 1 + c, let_1 = -3 % 3 != false + -3 == ("" | null) >= ("bar" < "a");
                }
            }
            c = c + 1;
        }
        var let_1_2 = f6(null, 4);
        function f7(yield_1, let_1) {
            c = 1 + c, -1 + "a" + (-4 <= -0) + (("undefined" | Infinity) != "" < NaN);
            {
            }
        }
        var b_2 = f7((c = c + 1) + +function() {}());
    }
    var a_2 = f4([ , 0 ][1], [], (b_2 && (b_2[(c = c + 1) + {
        length: (c = 1 + c, +("foo" * Infinity + (2 << ""))),
        0: (c = 1 + c, c = c + 1, (23..toString() && -0) <= (true || 0))
    }.set] = (22 ^ "b") >= ([ , 0 ].length === 2 == 2))) - ((undefined | false) > 1 / NaN));
    function f8(b_1, await_1) {
        function f9(b_1, [], b_1_1) {
            {
                var brake17 = 5;
                do {
                    c = 1 + c, (2 & Infinity) - -4 % [] >= ((24..toString(), "c") != "" >> Infinity);
                } while ((c = 1 + c, false << false <= ([ , 0 ].length === 2) >>> -5 || (5 != "number") - (-0 > true)) && --brake17 > 0);
            }
            switch (c = 1 + c, ((await_1 && (await_1.in += 3 << "c")) === "b" * "c") - (22 - 22) * (24..toString() ^ [])) {
              case c = 1 + c, "b" > undefined & null !== "object" ^ null % 22 == (a && (a[c = 1 + c, 
                {} / 2 % (3 !== "a") - (([ , 0 ].length === 2 !== Infinity) >= (-5 > -4))] += false * 0)):
                ;
                break;

              case c = 1 + c, ([ , 0 ].length === 2 == "a") < - -3 <= ((a += [ , 0 ][1] <= 3) || 4 % [ , 0 ][1]):
                ;
                break;

              default:
                ;

              case c = 1 + c, (3 - 4) * (-3 >> 25) !== (5 ^ 23..toString()) >>> -5 / "foo":
                ;
                break;
            }
        }
        var await_1 = f9(b_2 && b_2.var, [ {} ]);
        function f10(yield_2, Infinity_2) {
            function f11(b_2, [], yield) {
            }
            var foo_1 = f11((c = 1 + c, (c = c + 1, "foo" <= this) - (4 < "" & -1 !== -4)), "");
            function f12(b_2, foo_1_2, async) {
            }
            var arguments_1 = f12((c = 1 + c, ({} === "b") * (false + []) - ((this || "foo") > (NaN | 38..toString()))));
            function f13(Infinity_2) {
            }
            var NaN = f13((c = 1 + c, !(a_1 && (a_1[(c = c + 1) + --b] %= "bar" >>> 0 > 22 << 22))), (c = 1 + c, 
            (b_1 && (b_1[a++ + (b_2 && typeof b_2.NaN == "function" && --_calls_ >= 0 && b_2.NaN(5))] = (foo_1 && (foo_1.async = Infinity <= NaN)) | (a && (a[c = 1 + c, 
            ([] < "foo" & false % 3) !== (await_1 >>>= 24..toString() / "function") % (0 ?? "number")] += -2 + "foo")))) + (arguments_1 = "object" + "undefined" && "a" / "b")));
        }
        var b_2_2 = f10();
    }
    var bar = f8();
}

var yield_2 = f0(--b + [][yield_2 && (yield_2.set = ("foo" >> "bar" >> ("bar" >= this)) - ("a" < 24..toString() < (yield_2 = -2 - [ , 0 ][1])))], --b + ([ --b + (yield_2 && typeof yield_2.null == "function" && --_calls_ >= 0 && yield_2.null(+function b_2() {
    if (c = 1 + c, c = c + 1, Infinity < /[a2][^e]+$/ | "number" / -5) {
        c = 1 + c, (yield_2 += null % NaN & (yield_2 && (yield_2[c = 1 + c, (-1 | -4) >> (24..toString() < Infinity) == (-5 === undefined) << (5 > 0)] = NaN >> -4))) - ("a" >> 3 && -0 ^ []);
    } else {
        c = 1 + c, (yield_2 && (yield_2[c = 1 + c, (c = c + 1, -2, this) - ((24..toString() | NaN) >= (-1 < Infinity))] += "number" > -0)) == (yield_2 %= true << NaN) ?? "" >> "foo" | "foo" * "function";
    }
}())), [ ..."" + yield_2, typeof f1 == "function" && --_calls_ >= 0 && f1(), --b + (typeof f0 == "function" && --_calls_ >= 0 && f0()), ...[ (c = c + 1) + a++, a++ + delete b, --b + --b ] ] ] || 6).toString()[{
    1.5: (c = c + 1) + (yield_2 || 3).toString()[typeof yield_2 == "function" && --_calls_ >= 0 && yield_2()],
    3: yield_2 && yield_2[(c = c + 1) + (typeof yield_2 == "function" && --_calls_ >= 0 && yield_2("number") || 5).toString()[{}]]
}.then]);

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0() {
    function f1() {
        const a_2 = (c += 1) + (b ||= a);
        return c += 1, (a++ + !0 || 6).toString()["function" == typeof a_2 && 0 <= --_calls_ && a_2((c = 1 + c, 
        ((a_2 && (a_2.Infinity = 2 ^ !0o644n)) | this >> 1 / 0) == (a_2 && (a_2[c = 1 + c, 
        typeof (2 % [] >>> -0 ?? 0)] += -3 != (c += 1, 24..toString())))))], --b + typeof foo_2;
    }
    var a = f1(..."" + a, (c += 1) + (("a" != 23..toString()) < (c += 1, "b" + (a && (a.undefined = !0)))));
    var b_2 = void 0;
    0 <= --_calls_ && f1(), --b;
    var a_1 = --b + b;
    var b_1;
    b_1 = 0, function() {
        switch (c = 1 + c, -3 ^ 5 % 24..toString() ^ 0) {
          case c = 1 + c, ([] - 1 == (24..toString() && /[a2][^e]+$/)) % (a && (a.in ^= NaN >> (b_1 && (b_1[c = 1 + c, 
            24..toString() != 24..toString() | 1 ?? (2 === [ , 0 ].length) * 38..toString() - (a && (a[c = 1 + c, 
            -1 - (a && (a[c = 1 + c, ((NaN <= {}) >> (/[a2][^e]+$/ ^ [])) / 0] *= !1)) != 25] += "" <= 38..toString()))] ||= 0)))):
          case c = 1 + c, (("object" === 23..toString()) + (a && (a[c = 1 + c, (null < {}) % (("bar" == 23..toString()) % !0)] %= 3))) / 3:
          case c = 1 + c, !1 + (a && (a[--b + {
                ...(c = 1 + c, c += 1, !0)
            }] = 23..toString() >>> "c" ^ !1)):
          case c = 1 + c, -1:
        }
    }((c = 1 + c, 24..toString(), 38..toString(), c = 1 + c, 23..toString(), c = 1 + c, 
    a_1 && (a_1[c = 1 + c, ("c" ^ 23..toString() / (1 / 0)) - (4 !== [])] %= "b"), b_1 && ({
        0: b_1[c = 1 + c, !0]
    } = {
        0: NaN
    }), c = 1 + c, a && ([ a[c = 1 + c, void 38..toString()] ] = [ 0 ]), a = !1)), function(expr12) {
        for (var key12 in c = 1 + c, expr12 = !1 << ("function" >> 24..toString() != (expr12 && (expr12.done += !0)))) {
            c = 1 + c;
            c = 1 + c;
        }
        c += 1;
    }(null), c = 1 + (c += 1);
    (function(b_1, await_1) {
        await_1 = function() {
            for (var brake17 = 5; c = 1 + c, 24..toString(), c = 1 + c, 0 < --brake17; ) {}
            switch (c = 1 + c, (NaN === (await_1 && (await_1.in += 3))) - 0 * (24..toString() ^ [])) {
              case c = 1 + c, 0 ^ 0 == (a && (a[c = 1 + c, {} / 2 % !0 - (!1 <= (2 === [ , 0 ].length !== 1 / 0))] += 0)):
              case c = 1 + c, (2 === [ , 0 ].length == "a") < 3 <= ((a += !0) || NaN):
                break;

              default:
              case c = 1 + c, 1 != (5 ^ 23..toString()) >>> NaN:
            }
        }(b_2 && b_2.var);
        var foo_1 = void (c = 1 + c, c += 1), NaN = (c = 1 + c, 38..toString(), c = 1 + c, 
        a_1 && (a_1[(c += 1) + --b] %= !1), c = 1 + c, void (b_1 && (b_1[a++ + (b_2 && "function" == typeof b_2.NaN && 0 <= --_calls_ && b_2.NaN(5))] = (foo_1 && (foo_1.async = 1 / 0 <= NaN)) | (a && (a[c = 1 + c, 
        ([] < "foo" & 0) != (await_1 >>>= 24..toString() / "function") % 0] += "-2foo")))));
    })();
}

var yield_2 = f0(--b + [][yield_2 && (yield_2.set = (0 >> (this <= "bar")) - ("a" < 24..toString() < (yield_2 = -2)))], --b + [ --b + (yield_2 && "function" == typeof yield_2.null && 0 <= --_calls_ && yield_2.null(+function() {
    c = 1 + c, c = 1 + (c += 1), yield_2 && (yield_2[c = 1 + c, c += 1, this - (!0 <= (NaN | 24..toString()))] += !1), 
    yield_2 %= 1;
}())), [ ..."" + yield_2, "function" == typeof f1 && 0 <= --_calls_ && f1(), --b + ("function" == typeof f0 && 0 <= --_calls_ && f0()), (c += 1) + a++, a++ + delete b, --b + --b ] ].toString()[{
    1.5: (c += 1) + (yield_2 || 3).toString()["function" == typeof yield_2 && 0 <= --_calls_ && yield_2()],
    3: yield_2 && yield_2[(c += 1) + ("function" == typeof yield_2 && 0 <= --_calls_ && yield_2("number") || 5).toString()[{}]]
}.then]);

console.log(null, a, b, c, 1 / 0, NaN, void 0);
```
```
original result:
null 102 -6 82 Infinity NaN undefined

uglified result:
null 102 -6 78 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
function f8(b_1) {
    function f9() {
        switch (console.log(0 * "c")) {
          case 0:
          case 0..toString():
        }
    }
    f9();
    function f10() {
        var NaN = b_1 && 0(NaN);
    }
    f10();
}

f8();
// output: NaN
// 
// minify: undefined
// 
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  evaluate
  inline
  reduce_vars
  side_effects
  unused
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 46b59b9259f..da9034f2ceb 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -12818,7 +12818,6 @@ Compressor.prototype.compress = function(node) {
                     left: make_node(AST_Number, node, { value: 0 }),
                     right: make_node(AST_Number, node, { value: 0 }),
                 });
-                if (node instanceof AST_Scope && node !== scope) return node;
             }));
             var body = [];
             if (fn.rest || !all(fn.argnames, function(argname) {


Test patch:
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 02735195018..c31d2823d99 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -7103,3 +7103,35 @@ issue_5230: {
     }
     expect_stdout: "42"
 }
+
+issue_5237: {
+    options = {
+        evaluate: true,
+        inline: true,
+    }
+    input: {
+        function f() {
+            (function() {
+                while (console.log(0/0));
+            })();
+            (function() {
+                var NaN = console && console.log(NaN);
+            })();
+        }
+        f();
+    }
+    expect: {
+        function f() {
+            (function() {
+                while (console.log(0/0));
+            })();
+            var NaN = console && console.log(NaN);
+            return;
+        }
+        f();
+    }
+    expect_stdout: [
+        "NaN",
+        "undefined",
+    ]
+}