Repository: mishoo/UglifyJS (JavaScript)

Issue:
ufuzz failure
```js
// original code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(async, foo) {
    try {
        {
            var expr2 = void b;
            for (async in expr2) {
                c = 1 + c;
                var await = expr2[async];
                {
                    return a++ + (typeof f2 == "function" && --_calls_ >= 0 && f2());
                }
            }
        }
    } catch (foo) {
        if (--b + (async && async.length)) {
            for (var brake5 = 5; a++ + (foo && foo.Infinity) && brake5 > 0; --brake5) {
                c = c + 1;
            }
        }
        {
            var foo_1 = function f1(async_1) {
                {
                    var b = function await() {
                        c = c + 1;
                        L32373: {
                        }
                    }(25, (c = 1 + c, ~((23..toString() === undefined) >>> (c = c + 1, "foo"))));
                }
                {
                    var brake11 = 5;
                    L32374: while ((c = c + 1) + typeof (typeof f3 == "function" && --_calls_ >= 0 && f3()) && --brake11 > 0) {
                        return a++ + (async += a++ + (typeof f1 == "function" && --_calls_ >= 0 && f1(2)));
                    }
                }
            }("object", "c");
        }
    } finally {
        for (var brake13 = 5; ((c = c + 1) + a++ || a || 3).toString() && brake13 > 0; --brake13) {
            for (var brake14 = 5; typeof await_1 !== "number" && brake14 > 0; --brake14) {
                var expr15 = {
                    foo: foo,
                    Infinity: a++ + {
                        async: async,
                        3: (c = 1 + c, foo && (foo[--b + ((0 === 1 ? a : b) || a || 3).toString()] /= (foo += (NaN < "c") + (2 - "a")) * (c = c + 1, 
                        "" ^ 1))),
                        next: (c = 1 + c, c = c + 1, -2 * 2 >> (22, 38..toString())),
                        NaN: (c = 1 + c, async *= (23..toString() !== "") % (c = c + 1, /[a2][^e]+$/) & (c = c + 1, 
                        23..toString() << ([ , 0 ].length === 2)))
                    }.a,
                    "": a++ + new function undefined(await_1) {
                        this.value = (async <<= false >= 1) ^ 38..toString() & this;
                        this.value = (null || 24..toString()) / (/[a2][^e]+$/ >> undefined);
                        c = 1 + c, ([ , 0 ].length === 2) >> 4 >> (c = c + 1, true) || (async += (22 ^ false) != ("a" ^ "number"));
                        c = 1 + c, 4 >> "b" != false % -0 !== "number" - "number" <= -2 - NaN;
                        c = 1 + c, (2 | "object") * (22 < 24..toString()) || async && (async.next += 25 <= "foo" <= -1 << 2);
                        c = 1 + c, await_1 && (await_1[0 === 1 ? a : b] += (async = 4 % null ^ "foo" << 0, 
                        ("undefined" ^ true) !== 5 / this));
                    }(),
                    __proto__: {
                        c: (c = 1 + c, ("foo" << 38..toString()) - ("foo" >= "c") << (c = c + 1, "object" != -0)),
                        async: (c = 1 + c, ("a" << 25 ^ 24..toString() <= 0) > ("c" === -4, -2 > -2)),
                        get [(c = 1 + c, c = c + 1, async = (async += [ , 0 ][1] <= -1) + (foo && (foo.b += NaN != 22)))]() {
                            c = 1 + c, foo && (foo.undefined += (async && ({
                                length: async.null
                            } = {
                                length: (-3, -0)
                            })) >>> (-4 ^ null)) && 38..toString() - "bar" | "bar" * {};
                        }
                    } || {},
                    value: --b + {
                        c: (c = 1 + c, ("number" | [ , 0 ].length === 2) != (false, 2) === (foo && (foo.async += -4 % -5)) < ("function" & 0))
                    }
                };
                L32375: for (var key15 in expr15) {
                    c = 1 + c;
                    var a_2 = expr15[key15];
                    var bar = a++ + ((3 * undefined < (3 === this)) + (-3 >> null << {} * -1)), async_2 = typeof bar == "function" && --_calls_ >= 0 && bar();
                }
            }
        }
        {
            var expr22 = --b + (typeof f0 == "function" && --_calls_ >= 0 && f0(typeof (--b + (typeof async == "function" && --_calls_ >= 0 && async(NaN, a++ + {
                then: (c = 1 + c, (-([ , 0 ].length === 2) ^ delete 4) / ("" + "b" | -0 ^ Infinity)),
                "\t": (c = 1 + c, Infinity / -0 - (-1 & 25) | (c = c + 1, "b") > (0 && -4)),
                next: (c = 1 + c, (true - -4 !== (foo = NaN < false)) - (Infinity * ([ , 0 ].length === 2) == (24..toString() & "b"))),
                NaN: (c = 1 + c, ("foo" >= "a") / ([ , 0 ].length === 2 & 2) < ("" === 5 ^ ("a", 
                "object")))
            }.c, b += a))), /[a2][^e]+$/));
            for (let key22 in expr22) {
                {
                    var brake23 = 5;
                    while (void function() {
                        var foo_1;
                        a++ + ([ foo_1 ] = [ (c = 1 + c, c = c + 1, foo && (foo.undefined >>= "undefined" & "b" ^ "c" << "bar")), (c = 1 + c, 
                        ("c" | 22) != -1 >> -1, (-3 && "a") - (22 || 3)), ..."" + key22 ]);
                    }() && --brake23 > 0) {
                        var foo_1 = {
                            set: {
                                NaN: (c = 1 + c, void (key22 && ([ key22[[].NaN] ] = [ (-0 ^ {}, -4 === "object") ]))),
                                length: (c = 1 + c, (!-2 | undefined !== -3) << (c = c + 1, -1 | "bar")),
                                null: (c = 1 + c, +(3 ^ [ , 0 ][1] ^ 1 % true)),
                                b: (c = 1 + c, (c = c + 1, -4) != this <= "" || (foo && (foo[c = 1 + c, foo && (foo[--b + --b] %= Infinity << 2 === (async && (async.then ^= -1 > 1)) ^ 25 << "object" >= ("c" && 2))] *= "" || Infinity)) !== (key22 && (key22[c = 1 + c, 
                                (+ -5 && (3 && -5)) !== (1 != 25 === ({} ^ "function"))] += -1 >> "foo")))
                            }[--b + {}.a]
                        }[(c = c + 1) + ({
                            a: (c = 1 + c, +(NaN / 2) != (true > -1 & "object" == false)),
                            ...(c = 1 + c, (5 >= [] | ("b" | [ , 0 ][1])) != (null > NaN) / (23..toString() === false)),
                            set: (c = 1 + c, (NaN * "" > -5 - "undefined") / (([], undefined) + (22 <= "a")))
                        }[a++ + (b = a)] || a || 3).toString()];
                    }
                }
            }
        }
    }
    try {
        try {
            void a;
        } catch (foo_1) {
            c = c + 1;
            void b;
        } finally {
            {
                var Infinity_1 = function a_2(a_1, async_1) {
                    if (--b + (async_1 && async_1[a_1 && a_1[c = 1 + c, ("a", "") - (-4 && 23..toString()) >> ("" * 24..toString() > (-4, 
                    "object"))]])) {
                        var brake34 = 5;
                        while (async_1 && typeof async_1.a == "function" && --_calls_ >= 0 && (c = 1 + c, 
                        async_1 && (async_1.null += !(22 >> true) || +(async_1 += -2 & 25)), async_1.a)(...[]) && --brake34 > 0) {
                            if (c = 1 + c, ("undefined" | -1) >= (Infinity | 38..toString()) ^ ("number" <= "number") + (async && (async.value += "undefined" < undefined))) {
                                c = 1 + c, ((-3 ^ "") > -4 * 1) >>> (("function" | 38..toString()) >>> ("" <= []));
                            }
                        }
                    }
                    return a--;
                }("undefined");
            }
            switch (a++ + +(((true ^ 22) !== (Infinity_1 && (Infinity_1[c = 1 + c, foo && (foo.var &= 22 / 22 - (1 >>> 2) ^ (23..toString() === this || (async <<= "object" > "bar")))] += {} ^ "foo"))) > (24..toString() !== false && 23..toString() == ""))) {
              case (c = c + 1) + []:
                return (c = c + 1) + (((c_2, arguments) => --b + {}.length)((c = 1 + c, ("foo" << -5 !== (-1 != "foo")) > (Infinity / 38..toString() !== (24..toString() === /[a2][^e]+$/))), undefined) || a || 3).toString();
                {
                    var brake40 = 5;
                    do {
                        {
                            var brake41 = 5;
                            while (!function undefined_1() {}() && --brake41 > 0) {
                                c = 1 + c, (Infinity_1 && (Infinity_1.set = undefined >> "a" >= (5 && 38..toString()))) & (24..toString() - 2 || 22 && [ , 0 ].length === 2);
                                c = 1 + c, -0 < "b" > "number" + "b" !== ((Infinity_1 += "object" - {}) !== (24..toString() ^ "foo"));
                                c = 1 + c, Infinity_1 && (Infinity_1[{}.next] = (NaN ^ -3, "a" || "a") != (async && (async[--b + (typeof f0 == "function" && --_calls_ >= 0 && f0())] *= 25 | /[a2][^e]+$/ && (async && ([ async[c = 1 + c, 
                                +(this == true) + (("b" == this) << ({} & "c"))] ] = [ 1 === 24..toString() ])))));
                                c = 1 + c, this % "bar" >>> 24..toString() - 24..toString(), -1 - "bar" == "c" % Infinity;
                            }
                        }
                    } while ((b |= a) && --brake40 > 0);
                }
                break;

              case a++ + new function c_1(c) {
                    this[a++ + --b] = (Infinity_1 && (Infinity_1[c = 1 + c, (0 & []) * (5 <= 24..toString()) % (("function", 
                    -1) || ("c", -3))] *= 38..toString() >>> 2)) * ("number" >= -5) * ((-0 || this) !== (c = c + 1, 
                    2)) / ((foo && (foo.__proto__ += (24..toString() | "undefined") !== ([ , 0 ].length === 2) <= 5)) != void (async = 38..toString() + "b")) >= !(async && (async[0 === 1 ? a : b] += (void "function" > -"") << (-3 - Infinity <= "c" >>> "c")));
                }():
                {
                    return {
                        async: async,
                        length: --b,
                        3: /[abc4]/g.exec(((c = 1 + c, (-1 == [] !== Infinity > "foo") < ("undefined" * -0 ^ "number" >> -5)) || b || 5).toString()),
                        c: --b + ("number" >>> 22 !== "foo" + 23..toString() == ((foo && (foo.__proto__ ^= -1 ^ "b")) & (foo = -5 != -4))),
                        1.5: 1 === 1 ? a : b
                    };
                }
                {
                    --b + (Infinity_1 && typeof Infinity_1.a == "function" && --_calls_ >= 0 && Infinity_1.a("object", (c = 1 + c, 
                    "number" / 0 >= ("foo" ^ "undefined") == (Infinity_1 && (Infinity_1.var *= "c" > NaN && 24..toString() == this)))));
                    {
                        var expr50 = async;
                        for (var key50 in expr50) {
                            {
                                var brake51 = 5;
                                do {
                                    c = 1 + c, (async = ("c", "bar")) << (3 | "undefined") & (true << [ , 0 ][1]) * (c = c + 1, 
                                    1);
                                } while ((c = 1 + c, !(2 >= true === ("function" == {}))) && --brake51 > 0);
                            }
                        }
                    }
                }

              case (c = c + 1) + (typeof async == "function" && --_calls_ >= 0 && async()):
                ;
                c = c + 1;
                break;

              default:
            }
        }
    } finally {
        return;
        {
            var b_2 = function f2(yield, a_1, a_2) {
                return {
                    then: --b + {
                        [(c = 1 + c, a_1 && (a_1.in = ("bar" && null) === (this !== false) | (Infinity === 23..toString()) < (yield && (yield[c = 1 + c, 
                        25 < NaN ^ 4 === "a" | ("object" || "bar") < (0 != Infinity)] = 25 - 0))))]: (c = 1 + c, 
                        ~22 === 5 + NaN, 4 >= 24..toString() === (a_2 <<= -1 >= 23..toString()))
                    },
                    b: [ (c = 1 + c, a_2 && (a_2.Infinity = false % -1 & (c = c + 1, 23..toString())), 
                    ("b" + "bar") % (1 - "undefined")), (c = 1 + c, (true > "object" ^ undefined % 23..toString()) >>> (3 < this, 
                    -"bar")), (c = 1 + c, (async && (async.b = false * "bar")) - (-5 !== undefined) == false >> true >= ([ , 0 ][1] >= -2)), (c = 1 + c, 
                    NaN !== ([ , 0 ].length === 2) === NaN * 3 ^ void "foo" - (null < 24..toString())) ].a,
                    Infinity: --b + (typeof async == "function" && --_calls_ >= 0 && async())
                }[a++ + ((c = c + 1, yield += "number" >= "a") ^ (Infinity & false) >> (foo = null % "foo"))];
                {
                    var expr58 = 1 === 1 ? a : b;
                    for (var key58 in expr58) {
                        {
                            var foo_1 = function f3(a_1) {
                                c = 1 + c, (a_2 && (a_2[c = 1 + c, (2 - -2 >= (-0 >= Infinity)) >> (foo && (foo[--b + /[abc4]/g.exec(((c = 1 + c, 
                                -4 <= 0 & "foo" < NaN ^ "foo" == [ , 0 ][1] != (NaN | "a")) || b || 5).toString())] += [] << 4 ^ NaN - "undefined"))] = 3 - false) || 38..toString() < 22) % (undefined > [ , 0 ][1] ^ NaN == "bar");
                                c = 1 + c, ("foo" === "foo") > (/[a2][^e]+$/ && "") <= (25 & -0 ^ "" << 38..toString());
                            }` `;
                        }
                    }
                }
            }(a++ + (typeof f1 == "function" && --_calls_ >= 0 && f1()), -0);
        }
    }
}

var Infinity = f0();

console.log(null, a, b, c, Infinity, NaN, undefined);
```
```js
// uglified code
// (beautified)
var _calls_ = 10, a = 100, b = 10, c = 0;

function f0(async, foo) {
    try {
        for (async in void 0) {
            c = 1 + c;
            (void 0)[async];
            return a++ + ("function" == typeof f2 && 0 <= --_calls_ && f2());
        }
    } catch (foo) {
        if (--b + (async && async.length)) {
            for (var brake5 = 5; a++ + (foo && foo.Infinity) && 0 < brake5; --brake5) {
                c += 1;
            }
        }
        (function f1(async_1) {
            c = 1 + c, 23..toString(), c += 1, c += 1;
            var brake11 = 5;
            if ((c += 1) + typeof ("function" == typeof f3 && 0 <= --_calls_ && f3()) && 0 < --brake11) {
                return a++ + (async += a++ + (0 <= --_calls_ && f1()));
            }
        })();
    } finally {
        for (var brake13 = 5; ((c += 1) + a++ || a || 3).toString() && 0 < brake13; --brake13) {
            for (var brake14 = 5; "number" != typeof await_1 && 0 < brake14; --brake14) {
                var key15, expr15 = {
                    foo: foo,
                    Infinity: a++ + {
                        async: async,
                        3: (c = 1 + c, foo && (foo[--b + (b || a || 3).toString()] /= (foo += NaN) * (c += 1, 
                        1))),
                        next: (c = 1 + c, c += 1, -4 >> 38..toString()),
                        NaN: (c = 1 + c, async *= ("" !== 23..toString()) % (c += 1, /[a2][^e]+$/) & (c += 1, 
                        23..toString() << (2 === [ , 0 ].length)))
                    }.a,
                    "": a++ + new function undefined(await_1) {
                        this.value = (async <<= !1) ^ 38..toString() & this, this.value = 24..toString() / (/[a2][^e]+$/ >> undefined), 
                        c = 1 + c, (2 === [ , 0 ].length) >> 4 >> !0 || (async += !0), c = 1 + (c = 1 + (c += 1)), 
                        2 * (22 < 24..toString()) || async && (async.next += !1), c = 1 + c, await_1 && (await_1[b] += (async = 0, 
                        1 != 5 / this));
                    }(),
                    __proto__: {
                        c: (c = 1 + c, ("foo" << 38..toString()) - !0 << !0),
                        async: (c = 1 + (c += 1), !1 < (0 ^ 24..toString() <= 0)),
                        get [(c = 1 + c, c += 1, async = (async += !1) + (foo && (foo.b += !0)))]() {
                            c = 1 + c, foo && (foo.undefined += (async && ({
                                length: async.null
                            } = {
                                length: -0
                            })) >>> -4) && 38..toString();
                        }
                    },
                    value: --b + {
                        c: (c = 1 + c, 2 != ("number" | 2 === [ , 0 ].length) == (foo && (foo.async += -4)) < 0)
                    }
                };
                for (key15 in expr15) {
                    c = 1 + c;
                    var bar = a++ + ((NaN < (3 === this)) + (-3 << -1 * {}));
                    "function" == typeof bar && 0 <= --_calls_ && bar();
                }
            }
        }
        for (let key22 in --b + ("function" == typeof f0 && 0 <= --_calls_ && f0(typeof (--b + ("function" == typeof async && 0 <= --_calls_ && async(NaN, a++ + {
            then: (!0 ^ -(2 === [ , 0 ].length)) / ("b" | -0 ^ Infinity),
            "\t": (c = 1 + (c = 1 + c), Infinity / -0 - 25 | !1),
            next: (c = 1 + (c += 1), (5 !== (foo = !1)) - (Infinity * (2 === [ , 0 ].length) == ("b" & 24..toString()))),
            NaN: (c = 1 + c, !0 / (2 === [ , 0 ].length & 2) < 0)
        }.c, b += a))), /[a2][^e]+$/))) {
            !function() {
                var foo_1;
                a++, ([ foo_1 ] = [ (c = 1 + c, c += 1, foo && (foo.undefined >>= 0)), (c = 1 + c, 
                NaN), ..."" + key22 ]);
            }();
        }
    }
    try {
        var Infinity_1 = function(a_1, async_1) {
            if (--b + (async_1 && async_1[a_1 && a_1[c = 1 + c, "" - 23..toString() >> ("object" < "" * 24..toString())]])) {
                for (var brake34 = 5; async_1 && "function" == typeof async_1.a && 0 <= --_calls_ && (c = 1 + c, 
                async_1 && (async_1.null += +(async_1 += 24)), async_1.a)() && 0 < --brake34; ) {
                    c = 1 + c, (Infinity | 38..toString()) <= -1 ^ !0 + (async && (async.value += !1)) && (c = 1 + c, 
                    38..toString());
                }
            }
            return a--;
        }("undefined");
        switch (a++ + +((23 !== (Infinity_1 && (Infinity_1[c = 1 + c, foo && (foo.var &= 1 ^ (23..toString() === this || (async <<= !0)))] += "foo" ^ {}))) > (!1 !== 24..toString() && "" == 23..toString()))) {
          case (c += 1) + []:
            return (c += 1) + (c = 1 + c, 38..toString(), 24..toString(), (--b + {}.length || a || 3).toString());

          case a++ + new function(c) {
                this[a++ + --b] = !1 * (Infinity_1 && (Infinity_1[(0 & []) * (5 <= 24..toString()) % -1] *= 38..toString() >>> 2)) * (this !== 2) / ((foo && (foo.__proto__ += ("undefined" | 24..toString()) !== (2 === [ , 0 ].length) <= 5)) != void (async = 38..toString() + "b")) >= !(async && (async[b] += !1 << (-3 - Infinity <= 0)));
            }():
            return {
                async: async,
                length: --b,
                3: /[abc4]/g.exec((c = 1 + c, ((-1 == [] != "foo" < Infinity) < 0 || b || 5).toString())),
                c: --b + (0 !== "foo" + 23..toString() == ((foo && (foo.__proto__ ^= -1)) & (foo = !0))),
                1.5: a
            };

          case (c += 1) + ("function" == typeof async && 0 <= --_calls_ && async()):
            c += 1;
        }
    } finally {
        return;
    }
}

var Infinity = f0();

console.log(null, a, b, c, Infinity, NaN, void 0);
```
```
original result:
null 2663 -558 7224 Infinity NaN undefined

uglified result:
null 2663 -558 6949 Infinity NaN undefined
```
```js
// reduced test case (output will differ)

// (beautified)
function f0() {
    var expr15 = {
        __proto__: {
            get [0]() {
                0();
            }
        }
    };
    expr15[0];
}

f0();
// output: TypeError: 0 is not a function
// minify: 
// options: {
//   "mangle": false,
//   "output": {
//     "v8": true
//   },
//   "validate": true
// }
```
```
minify(options):
{
  "mangle": false,
  "output": {
    "v8": true
  }
}

Suspicious compress options:
  pure_getters
  reduce_vars
  unused
```


Discussion:

Patch:
diff --git a/lib/compress.js b/lib/compress.js
index 1c49ee793ce..6bc5d3b4dec 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3776,7 +3776,8 @@ merge(Compressor.prototype, {
         def(AST_Null, return_true);
         def(AST_Object, function(compressor, force) {
             return is_strict(compressor, force) && !all(this.properties, function(prop) {
-                return prop instanceof AST_ObjectKeyVal;
+                if (!(prop instanceof AST_ObjectKeyVal)) return false;
+                return !(prop.key == "__proto__" && prop.value._dot_throw(compressor, force));
             });
         });
         def(AST_ObjectIdentity, function(compressor, force) {


Test patch:
diff --git a/test/compress/pure_getters.js b/test/compress/pure_getters.js
index 2a20c339a07..935b3e31e46 100644
--- a/test/compress/pure_getters.js
+++ b/test/compress/pure_getters.js
@@ -1638,3 +1638,29 @@ nested_property_assignments_3: {
     }
     expect_stdout: "PASS"
 }
+
+issue_4939: {
+    options = {
+        pure_getters: "strict",
+        side_effects: true,
+    }
+    input: {
+        ({
+            __proto__: {
+                get p() {
+                    console.log("PASS");
+                },
+            },
+        }).p;
+    }
+    expect: {
+        ({
+            __proto__: {
+                get p() {
+                    console.log("PASS");
+                },
+            },
+        }).p;
+    }
+    expect_stdout: "PASS"
+}