Repository: mishoo/UglifyJS (language: javascript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

L30209: {
    var foo = a++ + !a, foo_1 = {
        [a ??= --b + --b]: +b
    }[a++ + (a && a.next)], b_2 = b++;
    L30210: {
        c = c + 1;
    }
    {
        var brake5 = 5;
        while ((c = c + 1) + (1 === 1 ? a : b) && --brake5 > 0) {
            a++ + !function() {
                try {
                    try {
                        {
                            var brake9 = 5;
                            do {
                                try {
                                    {
                                        var brake11 = 5;
                                        while ((c = 1 + c, ([] != [ , 0 ][1]) % ("object" == "number") != (-4 > -5 === -"")) && --brake11 > 0) {
                                            c = 1 + c, "a" - 0 >> (0 << -5) | void ([ , 0 ][1] && true);
                                        }
                                    }
                                } catch (foo_1) {
                                    c = 1 + c, "a" ^ this | {} == true | (24..toString() | 1) !== !5;
                                    c = 1 + c, (c = c + 1, c = c + 1, 24..toString()) || 24..toString() === -5 == (NaN ^ [ , 0 ].length === 2);
                                }
                            } while (b_2 && b_2[b_2] && --brake9 > 0);
                        }
                    } finally {
                        if (+function a_2() {
                        }()) {
                            c = c + 1;
                        }
                    }
                } catch (Infinity_1) {
                    --b + (b_2 && b_2.length);
                } finally {
                    {
                        var brake19 = 5;
                        while ((c = c + 1) + --a && --brake19 > 0) {
                            var b_1 = a++ + (a_2 && a_2[c = 1 + c, ~("c" % "" ?? [] + "c")]), a_2 = --b + (1 === 1 ? a : b);
                        }
                    }
                    {
                        var brake21 = 5;
                        while (+function() {
                            c = 1 + c, (c = c + 1, 2) >>> ([] && "b") << (b_1 && (b_1[--b + (b_1 -= (c = 1 + c, 
                            this != -4 !== 25 >>> 24..toString() ?? (-3 >= []) + (-3 >> -5)))] *= 22 - "bar" ^ (3 || "bar")));
                            c = 1 + c, (null % "a" || null + NaN) >>> (-1 ^ "function", 
                            "number" % "function");
                            c = 1 + c, +"object" <= ([ 3n ][0] > 2 ^ null) < ("" ^ [], 
                            "bar" >>> -5);
                            c = 1 + c, (([ , 0 ][1] === false) >>> (5 & 2)) % (38..toString() == "number" & (c = c + 1, 
                            "object"));
                            c = 1 + c, c = c + 1, c = c + 1, c = c + 1, -4;
                        }() && --brake21 > 0) {
                            var brake27 = 5;
                            do {
                                return c = 1 + c, ("foo" != 0 ^ -2 < []) == ("bar" !== null && 5 ^ "c");
                            } while ((c = c + 1) + (typeof f0 == "function" && --_calls_ >= 0 && f0()) && --brake27 > 0);
                        }
                    }
                }
            }();
        }
    }
    {
        ~("a" >= Infinity != 24..toString() / "foo" | ((-42n).toString() | -5) << ({} && "foo"));
    }
    var a_1 = (c = c + 1) + (0 in []), bar = !function bar_1() {
        {
            for (var brake33 = 5; (c = c + 1) + (typeof bar_1 == "function" && --_calls_ >= 0 && bar_1(-5)) && brake33 > 0; --brake33) {
                var a = a && typeof a.static == "function" && --_calls_ >= 0 && a.static`${c = 1 + c, 
                (a && (a.c >>= ("function" ^ -2) != -0 <= 0)) % (("" || false) / ("number" | null))}${c = 1 + c, 
                (NaN >>> 0 != (null ^ "function")) > (-2 - NaN <= 1 % 24..toString())}${c = 1 + c, 
                (b_2 && ([ b_2[/[abc4]/.test(((c = 1 + c, ("undefined" < this ^ ("object" ^ 1)) - ((-2 === -4) <= (23..toString() || undefined))) || b || 5).toString())] ] = [ ("" && [ , 0 ][1]) >= (24..toString() == "a") ])) <= (foo_1 && (foo_1[[ (c = 1 + c, 
                (-2 ?? []) % (/[a2][^e]+$/ > false) === (5 | 2) * (NaN % Infinity)), (c = 1 + c, 
                b_2 && (b_2[foo >>= --b] += -5 - "foo" - (-0 >> -0) || ([] ?? 3) - 3 % -2)) ].foo] = ("function" <= 22) % (this & "number")))}tmpl`;
            }
        }
        {
            var expr35 = a++ + (typeof f1 == "function" && --_calls_ >= 0 && f1`\\
${void a}`);
            for (var [ key35 ] in expr35) {
                c = 1 + c;
                var foo_1 = expr35[key35];
                c = c + 1;
            }
        }
        for (var brake37 = 5; --b + (b_2 && b_2.then) && brake37 > 0; --brake37) {
            try {
                L30211: {}
            } catch (b_2) {
                try {
                    try {
                        var b;
                    } catch (a) {
                        c = 1 + c, (([ , 0 ][1] | 5) === (Infinity, NaN)) >> ((Infinity ^ {}) << (b && (b[c = 1 + c, 
                        (+0, -4, Number(0xdeadn << 16n | 0xbeefn)) % (22 - NaN > true >> "function")] += false ^ NaN)));
                    } finally {
                        c = 1 + c, delete ("foo" in (-42n).toString()) << (-2 - false | this << "number");
                        c = 1 + c, (2 === {} != ({} & [ , 0 ].length === 2)) * ("number" ** false >> ([ , 0 ].length === 2) / this);
                        c = 1 + c, (NaN >> "foo" >= false << Infinity) * ~(-0 && NaN);
                        c = 1 + c, (foo_1 = +25 >>> (1 << ([ , 0 ].length === 2))) >= (this & 0) % ([] ^ 0);
                    }
                } catch (Infinity) {
                    switch (c = 1 + c, (b_2 && (b_2.a += ("object" && "foo") | ([] | NaN))) / (2 != 25 ^ ("" && 0))) {
                      case c = 1 + c, "undefined" > "number" !== (22 === "foo") ^ 4 + 2 >= (-5 < -4):
                        ;

                      case c = 1 + c, ([ , 0 ].length === 2 ^ [ , 0 ][1]) << (2 && "undefined") >>> (-5 == 38..toString()) / ([] >>> -1):
                        ;
                        break;

                      case c = 1 + c, (-3 === -4 === ([ , 0 ].length === 2) < 22) < ((b_2 ^= "foo" ^ undefined) | Infinity >= -1):
                        ;
                        break;

                      default:
                        ;
                    }
                }
            }
        }
    }();
}

{
    var b_1 = function bar() {
        {
            var bar_1 = function f0() {
                if (([ a ] = [ -a ])) {
                    c = c + 1;
                }
                try {
                    if ((c = c + 1) + (typeof f2 == "function" && --_calls_ >= 0 && f2(undefined, --b + (a && a.__proto__)))) {
                        var brake55 = 5;
                        while (a && --brake55 > 0) {
                            c = c + 1;
                        }
                    }
                } finally {
                    return;
                }
            }(null);
        }
    }();
}

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var e = 10, n = 100, i = 10, c = 0, N = n++ + !n, u = (n ??= --i + --i, n++, n && n.next, 
i++);

c += 1;

for (var t = 5; (c += 1) + n && 0 < --t; ) {
    n++, a = f = r = o = void 0;
    try {
        try {
            var o = 5;
            do {
                try {
                    for (var r = 5; c = 1 + c, (0 != []) % !1 != 0 && 0 < --r; ) {
                        c = 1 + c;
                    }
                } catch (y) {
                    c = 1 + c, 24..toString(), c = (c = 1 + c) + 1 + 1, 24..toString() || (24..toString(), 
                    NaN);
                }
            } while (u && u[u] && 0 < --o);
        } finally {
            !function v() {}();
        }
    } catch (g) {
        --i, u && u.length;
    } finally {
        for (var f = 5; (c += 1) + --n && 0 < --f; ) {
            var a = n++ + (v && v[c = 1 + c, -1]), v = --i + n;
        }
        !function() {
            c = 1 + c, c += 1, a && (a[--i + (a -= (c = 1 + c, -4 != this !== 25 >>> 24..toString() ?? ([] <= -3) + -1))] *= 3), 
            c = 1 + c, NaN, c = 1 + (c = 1 + c), 38..toString(), c = 1 + (c += 1), 
            c = c + 1 + 1 + 1;
        }();
    }
}

Infinity, 24..toString(), (-42n).toString();

c += 1, function l() {
    for (var t = 5; (c += 1) + ("function" == typeof l && 0 <= --e && l(-5)) && 0 < t; --t) {
        var n = n && "function" == typeof n["static"] && 0 <= --e && n["static"]`${c = 1 + c, 
        (n && (n.c >>= !0)) % NaN}${c = 1 + c, (NaN >>> 0 != 0) > (-2 - NaN <= 1 % 24..toString())}${c = 1 + c, 
        (u && ([ u[/[abc4]/.test((c = 1 + c, (("undefined" < this ^ 1) - (!1 <= (23..toString() || undefined)) || f || 5).toString()))] ] = [ ("a" == 24..toString()) <= "" ])) <= (r && (r[[ (c = 1 + c, 
        NaN === NaN % Infinity * 7), (c = 1 + c, u && (u[N >>= --f] += [] - 1)) ].foo] = !1 % ("number" & this)))}tmpl`;
    }
    var i, o = n++ + ("function" == typeof f1 && 0 <= --e && f1`\\
${void 0}`);
    for ([ i ] in o) {
        c = 1 + c;
        var r = o[i];
        c += 1;
    }
    for (var f, a = 5; --f + (u && u.then) && 0 < a; --a) {}
}(), function d() {
    n = -n, c += 1;
    try {
        if ((c += 1) + ("function" == typeof f2 && 0 <= --e && f2(undefined, --i + (n && n.__proto__)))) {
            for (var t = 5; n && 0 < --t; ) {
                c += 1;
            }
        }
    } finally {
        return;
    }
}();

console.log(null, n, i, c, Infinity, NaN, undefined);
```
```
original result:
null -102 -5 137 Infinity NaN undefined

uglified result:
null -102 -5 140 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
var b;

var brake5 = 5;

while (--brake5) {
    (function() {
        try {
            (function a_2() {});
        } finally {
            var b_1 = a_2, a_2 = --b;
            console.log(b_1);
        }
    })();
}
// output: undefined
// undefined
// undefined
// undefined
// 
// minify: undefined
// NaN
// NaN
// NaN
// 
// options: {
//   "ie": true,
//   "module": false,
//   "output": {
//     "semicolons": false,
//     "v8": true
//   },
//   "toplevel": true,
//   "validate": true
// }
```
```
minify(options):
{
  "ie": true,
  "module": false,
  "output": {
    "semicolons": false,
    "v8": true
  },
  "toplevel": true
}

Suspicious compress options:
  dead_code
  evaluate
  inline
  loops
  side_effects

Suspicious options:
  ie
  rename
  toplevel
```



Discussion / hints:

Fix patch:
diff --git a/lib/compress.js b/lib/compress.js
index d902278dd2..7b1f6c552e 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -14372,7 +14372,13 @@ Compressor.prototype.compress = function(node) {
                 if (!all(def.orig, function(sym) {
                     if (sym instanceof AST_SymbolConst) return false;
                     if (sym instanceof AST_SymbolFunarg) return !sym.unused && def.scope.resolve() !== fn;
-                    if (sym instanceof AST_SymbolLambda) return !compressor.option("ie") || sym.scope === def.scope;
+                    if (sym instanceof AST_SymbolLambda) {
+                        if (!compressor.option("ie")) return true;
+                        if (sym.scope === def.scope) return true;
+                        return !all(def.orig, function(decl) {
+                            return !(decl instanceof AST_SymbolVar);
+                        });
+                    }
                     if (sym instanceof AST_SymbolLet) return false;
                     return true;
                 })) return;


Test patch:
diff --git a/test/compress/ie.js b/test/compress/ie.js
index 8eb139b5e7..2e049b4f9c 100644
--- a/test/compress/ie.js
+++ b/test/compress/ie.js
@@ -3476,6 +3476,43 @@ issue_5350_ie: {
 }
 
 issue_5958: {
+    options = {
+        dead_code: true,
+        evaluate: true,
+        ie: false,
+        inline: true,
+        loops: true,
+        sequences: true,
+        toplevel: true,
+    }
+    input: {
+        "use strict";
+        while (function() {
+            if (a === console.log("PASS")) {
+                var a = function b() {};
+                try {
+                    a++;
+                } catch (b) {
+                    b[a];
+                }
+            }
+        }());
+    }
+    expect: {
+        "use strict";
+        if (a = void 0, a === console.log("PASS")) {
+            var a = function b() {};
+            try {
+                a++;
+            } catch (b) {
+                b[a];
+            }
+        }
+    }
+    expect_stdout: "PASS"
+}
+
+issue_5958_ie: {
     options = {
         dead_code: true,
         evaluate: true,
@@ -3511,3 +3548,75 @@ issue_5958: {
     }
     expect_stdout: "PASS"
 }
+
+issue_5961: {
+    options = {
+        ie: false,
+        inline: true,
+        toplevel: true,
+    }
+    input: {
+        for (var a in [ 1, 2 ]) {
+            (function() {
+                try {
+                    (function f() {});
+                } finally {
+                    var b = f, f = "FAIL";
+                    console.log(b || "PASS");
+                }
+            })();
+        }
+    }
+    expect: {
+        for (var a in [ 1, 2 ]) {
+            b = void 0;
+            f = void 0;
+            try {
+                (function f() {});
+            } finally {
+                var b = f, f = "FAIL";
+                console.log(b || "PASS");
+            }
+        }
+    }
+    expect_stdout: [
+        "PASS",
+        "PASS",
+    ]
+}
+
+issue_5961_ie: {
+    options = {
+        ie: true,
+        inline: true,
+        toplevel: true,
+    }
+    input: {
+        for (var a in [ 1, 2 ]) {
+            (function() {
+                try {
+                    (function f() {});
+                } finally {
+                    var b = f, f = "FAIL";
+                    console.log(b || "PASS");
+                }
+            })();
+        }
+    }
+    expect: {
+        for (var a in [ 1, 2 ]) {
+            b = void 0;
+            f = void 0;
+            try {
+                (function f() {});
+            } finally {
+                var b = f, f = "FAIL";
+                console.log(b || "PASS");
+            }
+        }
+    }
+    expect_stdout: [
+        "PASS",
+        "PASS",
+    ]
+}