Repository: mishoo/UglifyJS (language: javascript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

async function* f0(arguments_2) {
    function f1(bar_1) {
        function f2() {
            function f3(foo_1) {
            }
            var a_1 = f3((c = 1 + c, (null !== 23..toString()) % ("b" ^ "undefined") >>> ((-5 | -3) == {} / 25)), (c = 1 + c, 
            c = c + 1, "bar" !== 4 ^ "undefined" * -5));
            function f4() {
            }
            var bar = f4();
            function f5(bar_2) {
            }
            var foo = f5(Infinity, {});
            function f6(foo, b_2, bar_1 = 25) {
            }
            var arguments_2_2 = f6();
        }
        var b_2 = f2("object", (c = c + 1) + /[abc4]/.test(((c = c + 1) + {
            Infinity: (c = 1 + c, (("c" ^ null) !== ~"") >>> (("function" ^ -0) >= true >> /[a2][^e]+$/)),
            set: (c = 1 + c, (bar_1 = "" >> -1 != void "b") || "a" + "number" <= "number" ** "b"),
            Infinity: (c = 1 + c, ([ , 0 ][1] === 1) <= Infinity << NaN ^ (-0 === [] ^ 1 << [ , 0 ][1]))
        } || b || 5).toString()));
    }
    var b_1 = f1((c = c + 1) + b--, b >>>= a, 23..toString());
    function f7() {
        try {
            {
                var brake2 = 5;
                do {
                    {
                        var expr3 = (c = c + 1) + +function async_1() {
                        }();
                        for (var key3 in expr3) {
                            c = 1 + c;
                            var b_1 = expr3[key3];
                            c = 1 + c, ((true | 25) & 0 / 24..toString()) <= (0 ^ 38..toString()) - (22 || "undefined");
                        }
                    }
                } while ((a++ + (b ^= a) || a || 3).toString() && --brake2 > 0);
            }
        } catch (b_1) {} finally {
            try {
                return c = 1 + c, (arguments_2 && (arguments_2.in &= "foo" > -3)) % (4 == -5) | (c = c + 1, 
                []) + (Infinity > -1);
            } finally {
                c = 1 + c, ("" === 24..toString()) - (38..toString() == 38..toString()) ^ (b_1 && (b_1[c = 1 + c, 
                [ , 0 ][1] + -4 != false + "function", arguments_2 && (arguments_2.static = -0 / {} ^ [ , 0 ][1] < {})] += "object" ^ true) || this < this);
            }
            a++ + (arguments_2 && typeof arguments_2.length == "function" && --_calls_ >= 0 && arguments_2.length((c = 1 + c, 
            "bar" < 23..toString() ^ (b_1 && (b_1.async = "number" >>> !0o644n)) ^ -4 > "object" !== 23..toString() < /[a2][^e]+$/)));
            {
                var brake9 = 5;
                do {
                    return c = 1 + c, c = c + 1, -5 * 2 >>> (undefined == null);
                } while (a++ + /[abc4]/g.exec(((c = 1 + c, ((-4 < -5) >>> (24..toString() & NaN)) * ((-3, 
                -3) + ("c" <= 23..toString()))) || b || 5).toString()) && --brake9 > 0);
            }
            c = c + 1;
        }
        {
            var brake12 = 5;
            while (a++ + delete (arguments_2 && (arguments_2[a++ + (arguments_2 && typeof arguments_2.var == "function" && --_calls_ >= 0 && arguments_2.var())] /= (-1 & -1) < -3 << -1 ^ (arguments_2 = (null | 5) != "number" << null))) && --brake12 > 0) {
                var expr13 = 1 === 1 ? a : b;
                L39665: for (let key13 in expr13) {
                    c = 1 + c;
                    const b_1_2 = expr13[key13];
                    {
                        var brake14 = 5;
                        L39666: do {
                            try {
                                c = 1 + c, ((5 & "undefined") << ("b" <= "function")) / ((Infinity, 
                                3) << ([] <= -2));
                            } catch (c_2) {
                            }
                        } while (--b + (undefined in [ (c = 1 + c, false + 25 != (b_1 && (b_1[c = 1 + c, 
                        (arguments_2 && (arguments_2.next += Infinity + "function")) % (undefined && 2) && (38..toString() | "undefined" || arguments_2 && (arguments_2.async += -4 % "undefined"))] += null * "foo")) && "bar" % false % (2 << "function")) ]) && --brake14 > 0);
                    }
                }
            }
        }
    }
    var b_1 = f7(a++ + delete ((false / "number" >= ("b" <= this)) + -(38..toString() != "object")), [ typeof f8 == "function" && --_calls_ >= 0 && f8("number"), --b + (a++ + (arguments_2 && typeof arguments_2.async == "function" && --_calls_ >= 0 && arguments_2.async())) ].foo, (c = c + 1, 
    "") == "a" >= -1 ^ (b_1 && (b_1.var = [] !== "number")) << (/[a2][^e]+$/ < -2));
}

var arguments_2 = f0().next().done;

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

async function* f0(n) {
    b--, b >>>= a, ((c = (c += 1) + 1 + 1) + {
        Infinity: 1,
        set: !0,
        Infinity: (c = 1 + (c = 1 + (c = 1 + c)), 0)
    } || b || 5).toString(), c = 1 + (c = 1 + c);
    var t = void (c += 1);
    a++, "function" == typeof f8 && 0 <= --_calls_ && f8("number"), --b, a++, n && "function" == typeof n.async && 0 <= --_calls_ && n.async(), 
    c += 1, t && (t.var = !0);
    try {
        var o = 5;
        do {
            var i, r = (c += 1) + NaN;
            for (i in r) {
                c = 1 + c;
                var l = r[i];
                c = 1 + c;
            }
        } while ((a++ + (b ^= a) || a || 3).toString() && 0 < --o);
    } catch (l) {} finally {
        try {
            return c = 1 + c, n && (n.in &= !1), void (c += 1);
        } finally {
            c = 1 + c, l && (l[c = 1 + c, n && (n.static = 0)] += 1);
        }
        a++, n && "function" == typeof n.length && 0 <= --_calls_ && n.length((c = 1 + c, 
        !1 ^ (l && (l.async = "number" >>> !0o644n)) ^ !1));
        var e = 5;
        do {
            return c = 1 + c, void (c += 1);
        } while (a++ + /[abc4]/g.exec((c = 1 + c, (b || 5).toString())) && 0 < --e);
        c += 1;
    }
    for (var f = 5; a++ + (n && (n[a++ + (n && "function" == typeof n.var && 0 <= --_calls_ && n.var())] /= !1 ^ (n = !0)), 
    !0) && 0 < --f; ) {
        var v, y = a;
        for (v in y) {
            c = 1 + c, y[v];
            var s = 5;
            do {
                try {
                    c = 1 + c;
                } catch (c) {}
            } while (--b + (void 0 in [ (c = 1 + c, 25 != (l && (l[c = 1 + c, (n && (n.next += 1 / 0 + "function")) % void 0 && 38] += NaN)) && NaN) ]) && 0 < --s);
        }
    }
}

var arguments_2 = f0().next().done;

console.log(null, a, b, c, 1 / 0, NaN, void 0);
```
```
original result:
null 107 -104 18 Infinity NaN undefined

uglified result:
null 107 -104 17 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
async function* f0() {
    function f7() {
        try {
            0();
        } finally {
            try {
                return console.log();
            } finally {
                console.log();
            }
        }
    }
    f7();
}

f0().next();

console.log(undefined);
// output: 
// 
// undefined
// 
// minify: 
// undefined
// 
// 
// options: {
//   "compress": {
//     "passes": 1000000,
//     "sequences": 1000000,
//     "unsafe": true,
//     "unsafe_Function": true,
//     "unsafe_math": true,
//     "unsafe_proto": true,
//     "unsafe_regexp": true
//   },
//   "module": false,
//   "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
  },
  "module": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  dead_code
  inline
  passes
  reduce_vars
  side_effects
  unused

Suspicious options:
  rename
```



Discussion / hints:

Fix patch:
diff --git a/lib/compress.js b/lib/compress.js
index 9cf80de5d0..075e168d27 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -14330,18 +14330,22 @@ Compressor.prototype.compress = function(node) {
                         if (node instanceof AST_Return) return abort = true;
                         if (node instanceof AST_Scope) return true;
                     });
-                    stat.walk(new TreeWalker(function(node) {
+                    var tw = new TreeWalker(function(node) {
                         if (abort) return true;
                         if (node instanceof AST_Try) {
                             if (!node.bfinally) return;
                             if (all(node.body, function(stat) {
                                 stat.walk(find_return);
                                 return !abort;
-                            }) && node.bcatch) node.bcatch.walk(find_return);
+                            })) {
+                                if (node.bcatch) node.bcatch.walk(find_return);
+                                node.bfinally.walk(tw);
+                            }
                             return true;
                         }
                         if (node instanceof AST_Scope) return true;
-                    }));
+                    });
+                    stat.walk(tw);
                     return !abort;
                 };
             }


Test patch:
diff --git a/test/compress/awaits.js b/test/compress/awaits.js
index aafddaece8..05c5d2bc08 100644
--- a/test/compress/awaits.js
+++ b/test/compress/awaits.js
@@ -3729,3 +3729,88 @@ issue_5791: {
     ]
     node_version: ">=8"
 }
+
+issue_5842: {
+    options = {
+        awaits: true,
+        inline: true,
+    }
+    input: {
+        var a = "FAIL";
+        (async function() {
+            await function() {
+                try {
+                    try {
+                        return console;
+                    } finally {
+                        a = "PASS";
+                    }
+                } catch (e) {}
+                FAIL;
+            }();
+        })();
+        console.log(a);
+    }
+    expect: {
+        var a = "FAIL";
+        (async function() {
+            await function() {
+                try {
+                    try {
+                        return console;
+                    } finally {
+                        a = "PASS";
+                    }
+                } catch (e) {}
+                FAIL;
+            }();
+        })();
+        console.log(a);
+    }
+    expect_stdout: "PASS"
+    node_version: ">=8"
+}
+
+issue_5956: {
+    options = {
+        awaits: true,
+        inline: true,
+    }
+    input: {
+        (async function() {
+            await function() {
+                try {
+                    FAIL;
+                } finally {
+                    try {
+                        return 42;
+                    } finally {
+                        console.log("foo");
+                    }
+                }
+            }();
+        })();
+        console.log("bar");
+    }
+    expect: {
+        (async function() {
+            await function() {
+                try {
+                    FAIL;
+                } finally {
+                    try {
+                        return 42;
+                    } finally {
+                        console.log("foo");
+                    }
+                }
+            }();
+        })();
+        console.log("bar");
+    }
+    expect_stdout: [
+        "foo",
+        "bar",
+    ]
+    node_version: ">=8"
+}
diff --git a/test/compress/yields.js b/test/compress/yields.js
index eebdf4b8cb..88fee90bb3 100644
--- a/test/compress/yields.js
+++ b/test/compress/yields.js
@@ -2302,3 +2302,46 @@ issue_5842: {
     expect_stdout: "PASS"
     node_version: ">=10"
 }
+
+issue_5956: {
+    options = {
+        inline: true,
+    }
+    input: {
+        (async function*() {
+            (function() {
+                try {
+                    FAIL;
+                } finally {
+                    try {
+                        return console;
+                    } finally {
+                        console.log("foo");
+                    }
+                }
+            })();
+        })().next();
+        console.log("bar");
+    }
+    expect: {
+        (async function*() {
+            (function() {
+                try {
+                    FAIL;
+                } finally {
+                    try {
+                        return console;
+                    } finally {
+                        console.log("foo");
+                    }
+                }
+            })();
+        })().next();
+        console.log("bar");
+    }
+    expect_stdout: [
+        "foo",
+        "bar",
+    ]
+    node_version: ">=10"
+}