Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(arguments_1, await_1, [ await, foo ]) {
    {
        var expr1 = --b + [ a++ + arguments_1 ];
        for (var key1 in expr1) {
            c = 1 + c;
            var b = expr1[key1];
            try {
                --b + (--b + {
                    "-2": {
                        null: a++ + ((c = 1 + c, ((b += 2 === 4) && -0 & "foo") / (22 * "" & (-42n).toString() >> 2)) || a || 3).toString(),
                        [void function bar_1() {
                        }()]: a++ + --b,
                        [+function bar() {
                        }()]: typeof f2 == "function" && --_calls_ >= 0 && f2((c = 1 + c, (24..toString() <= null || /[a2][^e]+$/ - 24..toString()) & ("b" && this) == /[a2][^e]+$/ <= "a")),
                        NaN: --b + (typeof f1 == "function" && --_calls_ >= 0 && f1())
                    }[await && await[(c = c + 1) + (typeof undefined === "function")]],
                    next: a++ + b++
                }.length ? (c = c + 1) + (typeof arguments_1 == "function" && --_calls_ >= 0 && arguments_1(true, (c = c + 1) + typeof a_2) ? typeof (a++ + (38..toString() >>> Infinity > (NaN == 4)) % ((!0o644n != true) * (foo && (foo[c = 1 + c, 
                !0o644n === "object" | (-5 | -1) || (c = c + 1, [ 3n ][0] > 2 !== "function")] = -5 ^ "function")))) : a++ + /[abc4]/g.exec(((c = c + 1) + void function() {
                    {
                        var brake4 = 5;
                        L263933: while ((c = 1 + c, (c = c + 1, "c" - ([ 3n ][0] > 2)) ^ (await_1 && (await_1[c = 1 + c, 
                        (false & -5) < (5 == 2) ^ (4 ^ [] || !0o644n != NaN)] += 5 + true)) < (await += undefined ^ [])) && --brake4 > 0) {
                            c = 1 + c, ([ , 0 ][1] & "number") >>> 5 ** "number" > (this > 3 > ("undefined" ^ -3));
                        }
                    }
                    {
                        var brake6 = 5;
                        while ((c = 1 + c, ([ 3n ][0] > 2 < "function") - ("number" << !0o644n) - (await_1 /= -5 / undefined !== (this ^ "bar"))) && --brake6 > 0) {
                            c = 1 + c, (c = c + 1, [ , 0 ].length === 2 == 4) != ((c = c + 1, -3) == (b && (b[c = 1 + c, 
                            ({} ^ -4) != delete 4 && (b && (b[c = 1 + c, 1 % 5 < (23..toString() <= [ , 0 ][1]) === (NaN ^ [ 3n ][0] > 2) <= 5 % "undefined"] += "number" !== -1)) * (1 < 22)] %= 4 >= 2)));
                        }
                    }
                    L263934: for (var brake8 = 5; (c = 1 + c, (b && (b[c = 1 + c, (Number(0xdeadn << 16n | 0xbeefn) == -5) <= void "function" <= ("function" <= [] || -1 / "b")] = 0 !== "foo")) - (3 + "") ^ "function" - ([ 3n ][0] > 2) >> (2 <= null)) && brake8 > 0; --brake8) {
                        c = 1 + c, (-3 + "foo" && 1 == "undefined") !== (38..toString() & -3) - ("foo" ^ "b");
                    }
                }() || b || 5).toString())) : b--);
            } finally {
                L263935: for (var brake11 = 5; --b + (b = a) && brake11 > 0; --brake11) {
                    var expr12 = await_1;
                    for (var key12 in expr12) {
                        c = 1 + c;
                        var b_1 = expr12[key12];
                        "" in [ --b + /[abc4]/g.exec(((c = 1 + c, Number(0xdeadn << 16n | 0xbeefn) === [ 3n ][0] > 2 == 2 >>> 38..toString(), 
                        "number" << 5 > ("c" < "undefined")) || b || 5).toString()) ];
                    }
                }
            }
        }
    }
    {
        {
            var a_1 = function NaN_1(a_2, arguments_1_1, foo) {
                {
                    var brake16 = 5;
                    do {
                        switch (typeof [ ..."" + await ]) {
                          case a++ + (typeof f2 == "function" && --_calls_ >= 0 && f2()):
                            break;

                          case !b:
                            try {
                                c = 1 + c, (3 || []) == 1 > -4 ^ ("a" + Number(0xdeadn << 16n | 0xbeefn) ^ "foo" == {});
                            } catch (yield_2) {
                            } finally {
                            }
                            switch (c = 1 + c, arguments_1 = delete (0 > -5) && (foo && (foo[--b + (b += a)] += null - -3 ^ (-42n).toString() < true))) {
                              case c = 1 + c, ("number" ^ /[a2][^e]+$/ ^ Number(0xdeadn << 16n | 0xbeefn) + 4) << ((Number(0xdeadn << 16n | 0xbeefn) || -2) <= (Number(0xdeadn << 16n | 0xbeefn) <= "foo")):
                                ;
                                break;

                              default:
                                ;

                              case c = 1 + c, "bar" + [ , 0 ][1] - ("object" >> "bar") == ([ 3n ][0] > 2 == -3 == (-1 !== 2)):
                                ;

                              case c = 1 + c, (/[a2][^e]+$/ >>> true) ** (c = c + 1, 4) !== 0 * -5 >= (true == -4):
                                ;
                            }
                            break;

                          case await_1:
                            {
                            }
                            var await_1_1;

                          case a++:
                            {
                            }
                            break;
                        }
                    } while (--b + ((-2 != "a") >>> /[a2][^e]+$/ - null === (-2 !== [], "foo" || [])) && --brake16 > 0);
                }
                {
                    var brake24 = 5;
                    L263936: do {
                        {
                            var b_1 = function arguments_1_2(undefined, arguments_1) {
                                c = 1 + c, this / -0 % (this ^ "bar") >> ((5 | false) & 1 << false);
                                c = 1 + c, (-4 < Infinity && /[a2][^e]+$/ < this) < (5 & 0 && 25 ^ null);
                            }(undefined, (c = 1 + c, (4 & []) < (await += -3 === -3) | (false & -3) <= (1 & {})), 1);
                        }
                    } while (a++ + {
                        length: a++ + (typeof f1 == "function" && --_calls_ >= 0 && f1((c = 1 + c, (3 << "object" || (c = c + 1, 
                        "b")) == ("b" >= 4 === (b_1 && (b_1[c = 1 + c, (Number(0xdeadn << 16n | 0xbeefn) >>> "c" || (-42n).toString() ^ [ 3n ][0] > 2) ^ (c = c + 1, 
                        -0 * 23..toString())] = "function" >> -1))))))
                    }.undefined && --brake24 > 0);
                }
            }(++a);
        }
        {
            var a_2 = function await_2() {
                function f1() {
                    {
                        var brake29 = 5;
                        do {
                            c = 1 + c, false >= null !== ("c" !== 25) != ((await && (await[c = 1 + c, (await_1 && (await_1[c = 1 + c, 
                            (c = c + 1, Number(0xdeadn << 16n | 0xbeefn) || !0o644n) | (22 & false) / (22 - 3)] = [] ^ -1)) - void 23..toString() == !0o644n - 38..toString() >>> (-4 == "object")] = "number" >>> "bar")) == "a" + 3);
                        } while ((c = 1 + c, 38..toString() / ([ 3n ][0] > 2) === {} >> true === (arguments_1 = (-5 ^ null) > 22 % 0)) && --brake29 > 0);
                    }
                    c = c + 1;
                }
                var NaN = f1();
                function f2() {
                    function f3(NaN_1, NaN_1_1, foo_2) {
                    }
                    var Infinity_1 = f3({}, ...[ (c = 1 + c, (0 || 24..toString()) % (!0o644n / undefined), 
                    delete 3 <= (b && ({
                        undefined: b.c
                    } = {
                        undefined: -0 ^ "bar"
                    }))), (c = 1 + c, (Infinity_1 && ([ Infinity_1[(c = c + 1) + (foo && foo[c = 1 + c, 
                    (this !== [ 3n ][0] > 2) * (Infinity_1 && (Infinity_1.NaN %= null / this)) * ((22 > !0o644n) << "foo" / [ , 0 ][1])])] ] = [ -0 >>> undefined | void {} ])) & (a_1 && (a_1.foo = ("b" < (-42n).toString()) % (Infinity ^ "object")))), ..."" + b ], 23..toString());
                    function f4() {
                    }
                    var b_2 = f4();
                }
                var b_1 = f2([ 3n ][0] > 2, ++a);
                async function f5() {
                    let foo = --b + !function() {
                        c = 1 + c, (-1 + /[a2][^e]+$/ ^ -1 < 0) < ((2 || -0) ^ ([ , 0 ].length === 2) > -3);
                        c = 1 + c, "object" ^ /[a2][^e]+$/ ^ false == {} ^ (38..toString() <= 5 && "foo" != -1);
                        c = 1 + c, (3 >> "function") * (await = NaN | 23..toString()) === (4 << this) / ([ , 0 ][1] < -2);
                        c = 1 + c, "c" * (-42n).toString() <= (-1 | NaN) || await_1 && (await_1.Infinity = "" + 23..toString() < 3 + "object");
                    }(), Infinity_1 = a++ + b--;
                    {
                        return c = 1 + c, (undefined >= "b") >>> ([] < 24..toString()) < (NaN && (NaN.done <<= 22 | "bar" | [ , 0 ][1] >= "c"));
                    }
                    {
                        var brake37 = 5;
                        while ((c = 1 + c, foo && (foo.next <<= (2 ^ 4, 22 | [ , 0 ].length === 2, 5 * -0 <= ("bar" > null)))) && --brake37 > 0) {
                            c = 1 + c, c = c + 1, !0o644n + true !== 23..toString() >> 22;
                        }
                    }
                }
                var b_2 = f5(NaN);
                function f6() {
                    for (var brake39 = 5; (c = 1 + c, +("b" / Number(0xdeadn << 16n | 0xbeefn)) === (1 ^ /[a2][^e]+$/) << ("" && {})) && brake39 > 0; --brake39) {
                        c = 1 + c, (-1 == "a") > "object" % 0 != ((b && (b.then = (-0, 23..toString()))) != - -1);
                    }
                    try {
                        c = 1 + c, arguments_1 += (c = c + 1, true < {}) >> (/[a2][^e]+$/ + -5 == (-4 | 0));
                    } catch (bar_1) {
                    }
                }
                var yield_2 = f6(-0, !0o644n);
                function f7() {
                    var await_1_1 = (c = 1 + c, (23..toString() & 3 || -0 >> "a") > ((5 ^ -2) !== ({} != 38..toString()))), b_1 = (c = 1 + c, 
                    ((c = c + 1, [ , 0 ].length === 2) >= ([ , 0 ][1] != Infinity)) - ((-0 ^ -4) > NaN >> 5));
                    switch (c = 1 + c, (-1 > 38..toString() ^ (c = c + 1, {})) << ((null & "b") >> ([] && 0))) {
                      case c = 1 + c, -3 < 0 > (b_1 && (b_1.a -= 22 << "bar")) > (23..toString() < 24..toString() == 23..toString() - "function"):
                        ;
                        break;

                      case c = 1 + c, (b_1 && (b_1[(c = c + 1) + (-1 in [ (c = 1 + c, c = c + 1, 24..toString() + Infinity << !25), (c = 1 + c, 
                        (22 === "number") + (await && (await[c = 1 + c, c = c + 1, await && (await.NaN += (Number(0xdeadn << 16n | 0xbeefn) ^ []) >> (false ^ true))] = (-1, 
                        "undefined"))) - ((5 != "a") - (this >= true))), (c = 1 + c, c = c + 1, /[a2][^e]+$/ | [ , 0 ][1], 
                        "" / -5), (c = 1 + c, delete ("undefined" != "", null ^ 24..toString())), (c = 1 + c, 
                        await *= (38..toString() & "foo") === ([ 3n ][0] > 2 == [ , 0 ][1]) !== ((NaN && (NaN.foo ^= "number" ** 24..toString())) !== ("function", 
                        3))) ])] += (0 ^ 22) >> (([ 3n ][0] > 2) << -4))) != (undefined >>> this !== this >= null):
                        ;
                        break;

                      case c = 1 + c, ("c" & true || -3 * 0) !== (22 >= undefined) * ("object" > 5):
                        ;
                        break;

                      case c = 1 + c, await_1 && (await_1[(c = c + 1) + b++] = (("foo" ^ this) !== (false & "bar")) > (24..toString() <= "object" !== (2 == 24..toString()))):
                        ;
                    }
                }
                var await_1 = f7();
            }(~(0 * "bar" / (!0o644n >> "foo") >>> (true >> "object" || -3 <= 38..toString())), a++ + ((c = c + 1) + (typeof arguments_1_2 !== "undefined")));
        }
        if (--b + b--) {
            L263937: for (var brake46 = 5; a++ + -1 && brake46 > 0; --brake46) {
                var brake47 = 5;
                do {
                    c = c + 1;
                } while (--b + await && --brake47 > 0);
            }
        }
        L263938: {
            for (var brake50 = 5; a++ + (typeof await_1 == "function" && --_calls_ >= 0 && await_1(23..toString(), NaN, await)) && brake50 > 0; --brake50) {
                var await_1;
            }
        }
    }
}

var arguments_1 = f0("bar", {}, [ this, (c = c + 1) + (typeof a == "function" && --_calls_ >= 0 && a(undefined)), "" ]);

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```
// uglified code
// !!! beautify failed !!!
SyntaxError: Unexpected token: operator «=»
    at JS_Parse_Error.get (eval at <anonymous> (UglifyJS\tools\node.js:1:1), <anonymous>:71:23)
    at writeln (UglifyJS\test\ufuzz\index.js:1778:57)
    at errorln (UglifyJS\test\ufuzz\index.js:1788:5)
    at try_beautify (UglifyJS\test\ufuzz\index.js:1795:9)
    at log (UglifyJS\test\ufuzz\index.js:1898:9)
    at UglifyJS\test\ufuzz\index.js:2195:80
    at Array.forEach (<anonymous>)
    at Object.<anonymous> (UglifyJS\test\ufuzz\index.js:2129:20)
    at Module._compile (node:internal/modules/cjs/loader:1108:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
    at Module.load (node:internal/modules/cjs/loader:973:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:12)
    at node:internal/main/run_main_module:17:47
//
var _calls_=10,a=100,b=10,c=0;function f0(arguments_1,await_1,[await,foo]){var key1,expr1=--b+[a+++arguments_1];for(key1 in expr1){c=1+c;var b=expr1[key1];try{--b,--b+{"-2":{null:a+++(c=1+c,(((b+=!1)&&0)/(0&(-42n).toString()>>2)||a||3).toString()),undefined:a+++--b,NaN:"function"==typeof f2&&0<=--_calls_&&f2((c=1+c,(24..toString()<=null||/[a2][^e]+$/-24..toString())&1==this)),NaN:--b+("function"==typeof f1&&0<=--_calls_&&f1())}[await&&await[(c+=1)+!1]],next:a+++b++}.length?(c+=1,"function"==typeof arguments_1&&0<=--_calls_&&arguments_1(!0,(c+=1)+typeof a_2)?(a++,38..toString(),foo&&(foo[c=1+c,!0o644n==="object"|-1||(c+=1,2<3n!=="function")]=-5)):(a++,/[abc4]/g.exec(((c+=1)+void function(){for(var brake4=5;c=1+c,c+=1,"c"-(2<3n)^(await_1&&(await_1[c=1+c,!1^(4^[]||!0o644n!=NaN)]+=6))<(await+=void 0^[])&&0<--brake4;)c=1+c;for(var brake6=5;c=1+c,(2<3n<"function")-("number"<<!0o644n)-(await_1/=NaN!==("bar"^this))&&0<--brake6;)c=1+c,c+=1,c+=1,b&&(b[c=1+c,1!=(-4^{})&&!0*(b&&(b[c=1+c,1<(23..toString()<=0)==(NaN^2<3n)<=NaN]+=!0))]%=!0);for(var brake8=5;c=1+c,(b&&(b[c=1+c,(-5==Number(0xdeadn<<16n|0xbeefn))<=void 0<=("function"<=[]||NaN)]=!0))-"3"^"function"-(2<3n)>>!1&&0<brake8;--brake8)c=1+c,38..toString()}()||b||5).toString()))):b--}finally{for(var brake11=5;--b+(b=a)&&0<brake11;--brake11){var key12,expr12=await_1;for(key12 in expr12){c=1+c;expr12[key12];--b,/[abc4]/g.exec((c=1+c,Number(0xdeadn<<16n|0xbeefn),38..toString(),(b||5).toString()))}}}}var a_1=function(foo){var brake16=5;do{switch(typeof[...""+await]){case a+++("function"==typeof f2&&0<=--_calls_&&f2()):break;case!b:try{c=1+c,Number(0xdeadn<<16n|0xbeefn)}catch(yield_2){}switch(c=1+c,arguments_1=foo&&(foo[--b+(b+=a)]+=3^(-42n).toString()<!0)){case c=1+c,(0^Number(0xdeadn<<16n|0xbeefn)+4)<<((Number(0xdeadn<<16n|0xbeefn)||-2)<=(Number(0xdeadn<<16n|0xbeefn)<="foo")):break;default:case c=1+c,NaN==(2<3n==-3==1):case c=1+c,0**(c+=1,4)!==!0:}break;case await_1:case a++:}}while(--b+!1&&0<--brake16);var brake24=5;do{var b_1=(await+=!0,void(c=1+(c=1+(c=1+c))))}while(a+++{length:a+++("function"==typeof f1&&0<=--_calls_&&f1((c=1+c,3==(!1===(b_1&&(b_1[c=1+c,(Number(0xdeadn<<16n|0xbeefn)>>>"c"||(-42n).toString()^2<3n)^(c+=1,-0*23..toString())]=0))))))}.undefined&&0<--brake24)}(void++a),a_2=function(){var NaN=function(){for(var brake29=5;c=1+c,await&&(await[c=1+c,(await_1&&(await_1[c=1+c,0|(c+=1,Number(0xdeadn<<16n|0xbeefn)||!0o644n)]=-1^[]))-void 23..toString()==!0o644n-38..toString()>>>!1]=0),c=1+c,38..toString()/(2<3n)=={}>>!0==(arguments_1=!1)&&0<--brake29;);c+=1}();!function(){var Infinity_1=(c=1+c,24..toString(),b&&({undefined:b.c}={undefined:0}),c=1+c,Infinity_1&&([Infinity_1[(c+=1)+(foo&&foo[c=1+c,(this!==2<3n)*(Infinity_1&&(Infinity_1.NaN%=null/this))*((!0o644n<22)<<0/0)])]]=[0]),a_1&&(a_1.foo=("b"<(-42n).toString())%0),void 23..toString())}(++a);!async function(){--b,c=1+(1+c),38..toString(),c=1+c,await=NaN|23..toString(),c=1+c,"c"*(-42n).toString()<=(-1|NaN)||await_1&&(await_1.Infinity=""+23..toString()<"3object"),a++,b--,c=1+c,24..toString(),NaN&&(NaN.done<<=22)}();!function(){for(var brake39=5;c=1+c,0/0/Number(0xdeadn<<16n|0xbeefn)==1&&0<brake39;--brake39)c=1+c,b&&(b.then=23..toString());try{c=1+c,arguments_1+=(c+=1,(!0<{})>>!1)}catch(bar_1){}}();var await_1=function(){c=1+c,23..toString(),38..toString();var b_1=(c=1+c,(!0<=(2===[,0].length))-(NaN>>5<-4));switch(c=1+(c+=1),(38..toString()<-1^{})<<0){case c=1+(c+=1),(b_1&&(b_1.a-=22))<!0>(23..toString()<24..toString()==23..toString()-"function"):case c=1+c,(b_1&&(b_1[(c+=1)+(-1 in[(c=1+c,c+=1,24..toString()+1/0<<!1),(c=1+c,!1+(await&&(await[c=1+c,c+=1,await&&(await.NaN+=(Number(0xdeadn<<16n|0xbeefn)^[])>>1)]="undefined"))-(!0-(!0<=this))),(c=1+c,-0),(c=1+(c+=1),24..toString(),!0),(c=1+c,await*=("foo"&38..toString())===(2<3n==0)!=(3!==(NaN&&(NaN.foo^="number"**24..toString()))))])]+=22>>((2<3n)<<-4)))!=(void 0>>>this!==null<=this):case c=1+c,!1:break;case c=1+c,await_1&&(await_1[(c+=1)+b++]=(0!=("foo"^this))>(24..toString()<="object"!=(2==24..toString()))):}}()}((a++,c+=1));if(--b+b--)for(var brake46=5;a++-1&&0<brake46;--brake46)for(var brake47=5;c+=1,--b+await&&0<--brake47;);for(var brake50=5;a+++("function"==typeof await_1&&0<=--_calls_&&await_1(23..toString(),NaN,await))&&0<brake50;--brake50);}var arguments_1=f0("bar",{},[this,(c+=1)+("function"==typeof a&&0<=--_calls_&&a(void 0)),""]);console.log(null,a,b,c,1/0,NaN,void 0);
```
```
original result:
null 156 10 102 Infinity NaN undefined

uglified result:
SyntaxError: Unexpected token '='
    at new Script (node:vm:99:7)
    at createScript (node:vm:260:10)
    at Object.runInThisContext (node:vm:308:10)
    at node:internal/process/execution:77:19
    at [stdin]-wrapper:6:22
    at evalScript (node:internal/process/execution:76:60)
    at node:internal/main/eval_stdin:29:5
    at Socket.<anonymous> (node:internal/process/execution:205:5)
    at Socket.emit (node:events:390:22)
    at endReadableNT (node:internal/streams/readable:1307:12)
```
```js
// reduced test case (output will differ)

// (beautified)
(function await_2() {
    async function f5() {
        let foo = function() {
            await;
        }();
        return 0;
    }
    f5();
})();
// output: 
// minify: SyntaxError: Unexpected token '}'
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  dead_code
  inline
  reduce_vars
  sequences
  side_effects
  unused
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 2d826697492..2dea8ddae07 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3123,7 +3123,7 @@ merge(Compressor.prototype, {
                 if (prev) {
                     if (stat instanceof AST_Exit) {
                         if (stat.value || !in_async_generator(scope)) {
-                            stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat)).transform(compressor);
+                            stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat)).optimize(compressor);
                         }
                     } else if (stat instanceof AST_For) {
                         if (!(stat.init instanceof AST_Definitions)) {


Test patch:
diff --git a/test/compress/awaits.js b/test/compress/awaits.js
index 777359919f6..974134c603b 100644
--- a/test/compress/awaits.js
+++ b/test/compress/awaits.js
@@ -1246,3 +1246,37 @@ issue_4618: {
     expect_stdout: "function"
     node_version: ">=8"
 }
+
+issue_4717: {
+    options = {
+        inline: true,
+        reduce_vars: true,
+        sequences: true,
+        side_effects: true,
+        unused: true,
+    }
+    input: {
+        (function() {
+            async function f() {
+                var a = function() {
+                    await;
+                }();
+                return "FAIL";
+            }
+            return f();
+        })().then(console.log).catch(function() {
+            console.log("PASS");
+        });
+    }
+    expect: {
+        (async function() {
+            return function() {
+                await;
+            }(), "FAIL";
+        })().then(console.log).catch(function() {
+            console.log("PASS");
+        });
+    }
+    expect_stdout: "PASS"
+    node_version: ">=8"
+}