Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

export function f0() {
    function f2(arguments_1, b_2) {
        function f3(async_1, a_2) {
            c = 1 + c, ((23..toString(), 22) && "a" % [ , 0 ][1]) === (b_2 && (b_2[{
                1.5: (c = 1 + c, a_2 && (a_2[1 === 1 ? a : b] &= (b_2 += Infinity & undefined) / ("number" + 2) ^ ("number", 
                -4) < ("a" & undefined))),
                "\t": (c = 1 + c, (arguments_1 && (arguments_1[--b + typeof (c = 1 + c, ((c = c + 1, 
                "number") === 5 <= 24..toString()) - ("b" >> "c" <= (2, {})))] += [ , 0 ][1] <= true !== void null)) % delete (-1 <= "")),
                Infinity: (c = 1 + c, !("foo" ^ this) | -3 / -1 * ({} + this)),
                ...(c = 1 + c, (3 >= -3) % (23..toString() ?? 2) || (25, NaN) != (undefined === ([ , 0 ].length === 2)))
            }] = (arguments_1 += "" < 0) << "object" + false));
        }
        var a_1 = f3((c = 1 + c, (this < "" == (-0 == "function")) / (arguments_1 && (arguments_1[c = 1 + c, 
        ("b" >> -2 || {} != 5) % (this ^ 22 || 5 << 38..toString())] >>= /[a2][^e]+$/ >= -0) && (arguments_1 && (arguments_1[c = 1 + c, 
        -2 / 25 != 38..toString() < -5 === (arguments_1 && (arguments_1.next = {} >>> "foo")) - 2 % 24..toString()] += 22 + "")))) ? (c = 1 + c, 
        +(2 < 4 != (-5 & this))) : (c = 1 + c, (this === ([ , 0 ].length === 2) & 5 ** 24..toString()) >= (arguments_1 && (arguments_1.in |= 0 % 24..toString() >= (-5 && 3)))));
        function f4(yield_2_2, yield_2, yield) {
            if (c = 1 + c, c = c + 1, c = c + 1, "bar" ^ {}) {
                c = 1 + c, ("number" >>> "a" || 2 ^ [ , 0 ][1]) + (Infinity > 38..toString() > ("function" !== {}));
            }
            {
                return c = 1 + c, (null % "b" ?? -23..toString()) % ("b" % false && 3 === 24..toString());
            }
        }
        var bar_1 = f4(--b + /[abc4]/g.exec((--b + (b = a) || b || 5).toString()), (c = c + 1) + (23..toString() in {
            [(c = 1 + c, (void 25 & -"") >> ("function" == undefined | true << "foo"))]: (c = 1 + c, 
            (Infinity === NaN) >= (3 === "") | ("undefined" >> [] && 3 << NaN)),
            undefined(Infinity_1, a) {
                a += super.b;
                this[c = 1 + c, 3 / "number" / ("a" || undefined) === ((c = c + 1, -1) | ("" || [ , 0 ][1]))] += "b" ^ "number";
            },
            arguments_1: arguments_1,
            in: (c = 1 + c, (b_2 && (b_2[(c = 1 + c, (24..toString() % 38..toString() != 1 < 24..toString()) > (5 < ([ 3n ][0] > 2)) << ("b" !== {})) ? (c = 1 + c, 
            (-0 != Infinity) > (b_2 && (b_2.NaN *= 25 ^ "c")) > ((c = c + 1, 25) ^ -this)) : (c = 1 + c, 
            ((-3) ** -3 & 22 != 4) + void ("number" > 1))] ||= ([ , 0 ].length === 2) % 24..toString() * (23..toString() % "number"))) ^ "a" + 1 == "function" > /[a2][^e]+$/),
            Infinity: (c = 1 + c, (b_2 && (b_2.c &= -0 || /[a2][^e]+$/)) >= (23..toString() <= -2) ^ 24..toString() << -1 & delete [ , 0 ][1])
        }));
        function f5(yield, bar) {
            switch (c = 1 + c, null / -2 + (-4 == null) ^ [] * 5 != (undefined == [ , 0 ][1])) {
              case c = 1 + c, 38..toString() ^ 5 ^ undefined === 2 ^ ("c" ^ 0) - (c = c + 1, ""):
                ;
                break;

              case c = 1 + c, +"bar" >>> {} * /[a2][^e]+$/ <= (([ , 0 ].length === 2) < ([ , 0 ].length === 2)) * (b_2 && (b_2[c = 1 + c, 
                a_1 = (c = c + 1, bar && (bar.b = this > -3)) >= (-4 > 0 + {})] += 22 >> [ , 0 ][1])):
                ;

              case c = 1 + c, a_1 && (a_1.set = ((c = c + 1, /[a2][^e]+$/) && (-1 || false)) * (+[ , 0 ][1] * (22 ^ Infinity))):
                ;

              case c = 1 + c, ("b" % -2 & ([ , 0 ][1] && -1)) < (1 | -3 ?? {} == ""):
                ;
                break;
            }
            {
                var brake46 = 5;
                while ((c = 1 + c, ((bar = ([ , 0 ].length === 2) >= 3) !== (24..toString() ^ -2)) >>> (arguments_1 ^= 22 | 2, 
                true > "number")) && --brake46 > 0) {
                    c = 1 + c, (+25 > (this != 25)) / ((25 <= "bar") % (38..toString() > "c"));
                }
            }
        }
        var a_1 = f5();
        function f6() {
            function f7(a_1, b_1) {
            }
            var b_2 = f7((c = 1 + c, delete (3 ^ 3) >> ((false === ([ , 0 ].length === 2)) < ("c" && -4))));
            function f8(b_2) {
            }
            var bar_2 = f8("a", (c = 1 + c, c = c + 1, b_2 && ({
                undefined: b_2.var
            } = {
                undefined: this | 23..toString() || (c = c + 1, 22)
            })), (c = 1 + c, ("bar" - [] << ("object" != [ , 0 ][1])) - ((0 ^ 4) << ("" >= "b"))));
            function f9(foo_2, bar_1_1) {
            }
            var a_1 = f9((c = 1 + c, (bar_1 && (bar_1[c = 1 + c, (arguments_1 && (arguments_1[c = 1 + c, 
            ((-1 ^ 0) & 5 >> -4) !== (24..toString() != undefined != 3 >> true)] += "b" >= null)) ^ 23..toString() < ([ , 0 ].length === 2) || {} <= {} === "b" < "bar"] = "b" || -3)) >> ("" && -1) > ("bar" + 1 || /[a2][^e]+$/ ** "number")), (c = 1 + c, 
            null ** -5 >>> !"object" | (24..toString() ^ -1) !== (-5 || 23..toString())));
            function f10() {
            }
            var b = f10((c = 1 + c, (b_2 += (a_1 && (a_1.c = -0 + -2)) != "bar" + -1) !== (false << 2 === (5 == -0))), NaN);
        }
        var Infinity = f6("undefined");
        function f11(yield_2, a_1_1, bar) {
            function f12(async_2, NaN_2) {
            }
            var arguments_1_2 = f12();
            function f13(async, yield_1, arguments_1_2) {
            }
            var a_2 = f13("b", (c = 1 + c, (23..toString() === -2) * (([ , 0 ].length === 2) + /[a2][^e]+$/) + (1 <= "b" || 1 << "object")));
            function f14(a_1, bar) {
            }
            var undefined_1 = f14();
            function f15({}, Infinity_1) {
            }
            var a_1 = f15("", (c = 1 + c, -4 != -3 == "" % "object" & (22 ^ Number(0xdeadn << 16n | 0xbeefn)) % (Infinity !== "a")), (c = 1 + c, 
            (/[a2][^e]+$/ <= /[a2][^e]+$/ != ([ , 0 ].length === 2 & undefined)) >> ((-5 || 22) >>> ("a" ^ []))));
            function f16(undefined_1_2, c, a) {
            }
            var b_2 = f16(Infinity);
        }
        var a_1 = f11();
    }
    var bar_1 = f2();
    function f17() {
        var a;
        L25834: for (var brake49 = 5; (b = a) && brake49 > 0; --brake49) {
            var expr50 = typeof (true in {
                next: (c = 1 + c, (([ , 0 ].length === 2) >> "object" ?? -4 > -4) * ("" === 22 && (bar_1 <<= 25 >= "b"))),
                done: (c = 1 + c, (38..toString() !== "a" && "" == 3) != (/[a2][^e]+$/ << 24..toString() || (38..toString() || []))),
                length: (c = 1 + c, c = c + 1, 25 >= [ , 0 ][1] !== ("b" & NaN))
            });
            for (var key50 in expr50) {
                c = 1 + c;
                var NaN_1 = expr50[key50];
                c = c + 1;
            }
        }
    }
    var async_1 = f17();
    function f18(undefined_2, yield_1_1, yield_1) {
        for (var brake52 = 5; a++ + ((-1 != "b", -[ , 0 ][1]) <= +("bar" % -4)) && brake52 > 0; --brake52) {
            return +a;
        }
        var c_2 = (c = c + 1) + (5 in {
            c: +function() {
            }(),
            ...b = a,
            a: (c = c + 1) + (typeof yield_1 === "number"),
            "": --b + /[abc4]/g.exec(((c = 1 + c, c_2 && (c_2[--b] = (-3 & undefined && "object" + "foo") | (let_1 && (let_1[a++ + (typeof async_1_2 == "boolean")] -= -1 / 23..toString() <= (false || [ , 0 ][1]))))) || b || 5).toString())
        }), let_1 = --b + (yield_1_1 && (yield_1_1[/[abc4]/.test(((c = c + 1) + (1 === 1 ? a : b) || b || 5).toString())] = ("foo" ^ -2) << ({} & -0) > ("c" >> null ^ "c" / 4)));
    }
    var c_1 = f18();
}

var await = f0(void function() {
    var a_2 = /[abc4]/g.exec((--b + (bar_1 && bar_1.undefined) || b || 5).toString()), bar_1 = a++ + (a++ + /[abc4]/g.exec((a++ + ((undefined ^ "number") % ("b" >>> 24..toString()) >= (c = c + 1, 
    [ , 0 ][1]) * (2 ?? -4)) || b || 5).toString()));
    {
        return a_2 ??= new function(b) {
            {
                {
                    var brake4 = 5;
                    do {
                        if (c = 1 + c, (c = c + 1, 4 & /[a2][^e]+$/) - (undefined ^ -3) * (c = c + 1, "bar")) {
                            c = 1 + c, (b && (b[a++ + [ (c = 1 + c, a_2 += (-1 < false) / (23..toString() <= 1) > (1 / !0o644n ^ "c" >> 23..toString())) ]] += ([ , 0 ].length === 2 & 4) === (5, 
                            22))) | 2 >= 23..toString() == ("" === 22);
                        } else {
                            c = 1 + c, ([ , 0 ][1] - true) * (bar_1 += "c" + "") - ((undefined ?? 1) <= ("a" ^ -2));
                        }
                    } while (b && --brake4 > 0);
                }
                try {
                    L25829: for (var brake9 = 5; (c = 1 + c, ((/[a2][^e]+$/ ^ "undefined") >> (null > Number(0xdeadn << 16n | 0xbeefn))) / (-0 << -5 == -2 >>> [])) && brake9 > 0; --brake9) {
                        c = 1 + c, delete ("bar" !== "object") << ("a" === -2 ?? (b += "number" > ([ , 0 ].length === 2)));
                    }
                } finally {
                    c = 1 + c, (undefined && null) / (1 % ([ , 0 ].length === 2)) >= (c = c + 1, 24..toString() >>> "bar");
                    c = 1 + c, (-5 || "foo") != (a_2 >>>= 22 <= 5) === (c = c + 1, null) << (bar_1 && (bar_1[c = 1 + c, 
                    ("a" | 23..toString()) - (-5 - Infinity) < (b += [] === (-42n).toString()) / ([] >>> "foo")] += 3 !== 3));
                }
                for (var brake13 = 5; {
                    a: (c = 1 + c, 4 * 23..toString() >>> (38..toString() < "a") << (-4 & undefined ^ (b += 5 < NaN))),
                    NaN: (c = 1 + c, (-3 << undefined | 0 < true) ^ (undefined ^ "object") >= NaN - 0)
                }.undefined && brake13 > 0; --brake13) {
                    c = 1 + c, -(25 >= "bar") << ("b" / 23..toString() > (22 ?? "number"));
                }
                {
                    var expr15 = (c = c + 1) + (0 === 1 ? a : b);
                    for (var key15 in expr15) {
                        {
                        }
                    }
                }
            }
        }(-4);
    }
    c = c + 1;
    if (/[abc4]/g.exec(((c = c + 1) + (bar_1 && typeof bar_1.async == "function" && --_calls_ >= 0 && bar_1.async(a++ + (typeof f1 == "function" && --_calls_ >= 0 && f1(-0, --a)))) || b || 5).toString())) {
        var brake19 = 5;
        do {
            c = c + 1;
        } while ((c = c + 1) + delete b && --brake19 > 0);
    } else {
        var a_1 = function f1(undefined_2, a_2_2) {
            for (var brake22 = 5; --b + a++ && brake22 > 0; --brake22) {
                var bar_1 = a++ + (typeof f2 == "function" && --_calls_ >= 0 && f2((c = 1 + c, (24..toString() >> true ^ 1 === "c") < (c = c + 1, 
                24..toString() ?? 23..toString())), ""));
            }
            switch (--b + b--) {
              case a_2 && typeof a_2.value == "function" && --_calls_ >= 0 && (b--, a_2.value)(--b + --b):
                {
                    var brake25 = 5;
                    do {
                        try {
                            c = 1 + c, (38..toString() === true, NaN ^ 23..toString()) === !(-3 / ([ , 0 ].length === 2));
                        } catch (bar_2) {
                        } finally {
                        }
                    } while (function a_2_2() {
                    } && --brake25 > 0);
                }
                break;

              case typeof f3 == "function" && --_calls_ >= 0 && f3(0 === 1 ? a : b, typeof f2 == "function" && --_calls_ >= 0 && f2(..."" + bar_1, (c = 1 + c, 
                (a_2 && (a_2[(c = c + 1) + ((-5 ^ 22) * (-5 >= {}) == (a_2 && (a_2.static = ("a" ^ [ , 0 ].length === 2) + [] / NaN)))] >>>= "bar" / "bar" && 25 | 0)) > ((-42n).toString() ^ false ^ undefined !== [ , 0 ][1])), 2)):
                ;
                L25830: {
                    c = 1 + c, {} >= Infinity & (undefined || 5), false >>> false && (undefined_2 && (undefined_2[c = 1 + c, 
                    c = c + 1, 3 / true && (a_2 += "b" <= {})] += 25 - true));
                    c = 1 + c, (3 > -2 != (a_2_2 += [] ^ [ , 0 ].length === 2)) >> ("b" + 22 & (2, -0));
                    c = 1 + c, (false ^ "bar") > (4 == undefined) ^ ("bar" > undefined) * (-3 < undefined);
                    c = 1 + c, (c = c + 1, ([ , 0 ].length === 2) - "function") & ([ , 0 ].length === 2) + [ , 0 ][1] < this * 38..toString();
                }
                break;

              case a++ + (a_2_2 && typeof a_2_2.c == "function" && --_calls_ >= 0 && a_2_2.c("b", "foo", undefined)):
                {
                    var brake34 = 5;
                    L25831: do {
                        {
                            var expr35 = (c = 1 + c, (-1 > -4 ^ ("undefined" ^ Infinity)) !== ("function" === null ^ "object" & true));
                            for (var key35 in expr35) {
                                c = 1 + c, void ((1 !== 23..toString()) * (1 == "c"));
                            }
                        }
                    } while ((c = c + 1) + (("bar" && "number" && -0 << "a") ^ (this || 24..toString()) + "object" / Infinity) && --brake34 > 0);
                }
                break;

              case typeof undefined_2 == "function" && --_calls_ >= 0 && undefined_2():
                {
                    var brake37 = 5;
                    L25832: while (a_2_2 && --brake37 > 0) {
                        L25833: {
                        }
                    }
                }
                (c = c + 1) + +((false >>> -4 && (c = c + 1, "foo")) <= (undefined ** this >= (23..toString() == 2)));
                break;
            }
        }(bar_1 += "b", -1, -0);
    }
}());

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0() {
    var n;
    !function(e, i) {
        var t = function(n) {
            c = 1 + c, i && (i[{
                1.5: (c = 1 + c, n && (n[a] &= (i += void 0 & o) / "number2" ^ !0)),
                "\t": (c = 1 + c, (e && (e[--b + (c = 1 + c, typeof ((!0 === (c += 1, "number")) - !1))] += !0)) % !0),
                Infinity: !("foo" ^ this) | 3 * ({} + this),
                ...(c = 1 + (1 + c), 1)
            }] = (e += !1) << "object" + !1);
        }((c = 1 + c, void ((this < "" == 0) / (e && (e[c = 1 + c, !0 % (22 ^ this || 320)] >>= !1) && e && (e[c = 1 + c, 
        !0 === (e && (e.next = 0)) - 2] += "22")) ? c = 1 + c : (c = 1 + c, e && (e.in |= !1))))), o = (--b, 
        (--b + (b = a) || b || 5).toString(), c = 1 + (1 + (1 + (c + 1))), i && (i[c = 1 + c, 
        (5 < (2 < 3n)) << !0 < !0 ? (c = 1 + c, (-0 != o) > (i && (i.NaN *= 25)) > (c += 1, 
        25 ^ -this)) : (c = 1 + c, NaN)] ||= (2 === [ , 0 ].length) % "24" * NaN), c = 1 + c, 
        i && (i.c &= /[a2][^e]+$/), delete [ , 0 ][1], c = 1 + (1 + c + 1 + 1), t = function(n) {
            switch (0) {
              case c = 1 + (1 + (1 + c) + 1), 0 <= ((2 === [ , 0 ].length) < (2 === [ , 0 ].length)) * (i && (i[c = 1 + c, 
                c += 1, t = !1 <= (n && (n.b = -3 < this))] += 22)):
              case c = 1 + c, t && (t.set = (c += 1, 0 * (22 ^ o) * -1)):
                break;

              case c = 1 + c, !1:
            }
            for (var a = 5; c = 1 + c, (-26 !== (n = 3 <= (2 === [ , 0 ].length))) >>> (e ^= 22, 
            !1) && 0 < --a; ) {
                c = 1 + c;
            }
        }(), function() {
            var n = void (c = 1 + c), n = (c = 1 + c, c += 1, n && ({
                undefined: n.var
            } = {
                undefined: "23" | this || (c += 1, 22)
            }), void (c = 1 + (1 + (1 + c))));
            c = 1 + c, n && (n.c = -2);
        }());
        c = 1 + (1 + (1 + c));
    }(), b = void 0, a++ + !1 || (n = (c += 1) + (5 in {
        c: NaN,
        ...b = a,
        a: (c += 1) + !1,
        "": --b + /[abc4]/g.exec((c = 1 + c, (n && (n[--b] = 0) || b || 5).toString()))
    }), --b);
}

var await = f0(void function() {
    var n = /[abc4]/g.exec((--b + (e && e.undefined) || b || 5).toString()), e = a++ + (a++ + /[abc4]/g.exec((a++ + (2 * (c += 1, 
    0) <= NaN) || b || 5).toString()));
    if (void 0 === n) {
        for (var i = -4, t = 5; c = 1 + (1 + c + 1 + 1), e += "c", i && 0 < --t; ) {}
        try {
            for (var o = 5; c = 1 + c, (0 >> (+("" + (0xdeadn << 16n | 0xbeefn)) < null)) / !1 && 0 < o; --o) {
                c = 1 + c;
            }
        } finally {
            c = 1 + (1 + c + 1), c += 1, e && (e[c = 1 + c, 1 / 0 < (i += [] === "" + -42n) / 0] += !1);
        }
        for (var r = 5; {
            a: 46 << (0 ^ (i += !1)),
            NaN: (c = 1 + (1 + c), -3)
        }.undefined && 0 < r; --r) {
            c = 1 + c;
        }
        c += 1;
    }
}());

console.log(null, a, b, c, 1 / 0, NaN, void 0);

export {
    f0
};
```
```
original result:
null 104 undefined 67 Infinity NaN undefined

uglified result:
null 104 undefined 38 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
(function() {
    var a_2 = /[abc4]/g.exec();
    return a_2 ??= new function() {
        for (var brake13 = 5; 1; 0) {}
    }();
    (function f1() {
        a_2;
    });
})();
// output: Error: Script execution timed out after 700ms
// minify: 
// options: {
//   "compress": {
//     "passes": 1000000,
//     "sequences": 1000000,
//     "unsafe": true,
//     "unsafe_Function": true,
//     "unsafe_math": true,
//     "unsafe_proto": true,
//     "unsafe_regexp": true
//   },
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "compress": {
    "passes": 1000000,
    "sequences": 1000000,
    "unsafe": true,
    "unsafe_Function": true,
    "unsafe_math": true,
    "unsafe_proto": true,
    "unsafe_regexp": true
  },
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  dead_code
  inline
  passes
  side_effects

Suspicious options:
  rename
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 87e0f964ac8..9320d5a78a5 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -12898,8 +12898,8 @@ Compressor.prototype.compress = function(node) {
                     return cond.negate(compressor);
                   case "??":
                     return make_node(AST_Binary, self, {
-                        operator: "===",
-                        left: make_node(AST_Undefined, self).transform(compressor),
+                        operator: "==",
+                        left: make_node(AST_Null, self),
                         right: cond,
                     });
                 }


Test patch:
diff --git a/test/compress/nullish.js b/test/compress/nullish.js
index be9c752df07..b141d10bdc1 100644
--- a/test/compress/nullish.js
+++ b/test/compress/nullish.js
@@ -274,7 +274,7 @@ inline_binary_nullish: {
         })();
     }
     expect: {
-        if (void 0 === function() {
+        if (null == function() {
             while (console.log("foo"));
         }())
             while (console.log("bar"));
@@ -304,3 +304,42 @@ issue_4679: {
     expect_stdout: "PASS"
     node_version: ">=14"
 }
+
+issue_5266: {
+    options = {
+        inline: true,
+    }
+    input: {
+        [
+            42,
+            null,
+            false,
+            void 0,
+            "FAIL",
+        ].forEach(function (a) {
+            a ?? function() {
+                while (console.log(a));
+            }();
+        });
+    }
+    expect: {
+        [
+            42,
+            null,
+            false,
+            void 0,
+            "FAIL",
+        ].forEach(function (a) {
+            if (null == a) {
+                while (console.log(a));
+                return;
+            } else
+                return;
+        });
+    }
+    expect_stdout: [
+        "null",
+        "undefined",
+    ]
+    node_version: ">=14"
+}