tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

expression-autopsy.js (8799B)


      1 // |jit-test| skip-if: getBuildConfiguration('pbl')
      2 load(libdir + "asserts.js");
      3 load(libdir + "iteration.js");
      4 
      5 function check_one(expected, f, err) {
      6    var failed = true;
      7    try {
      8        f();
      9        failed = false;
     10    } catch (ex) {
     11        assertEq(ex.constructor.name, "TypeError");
     12        var s = ex.message;
     13        assertEq(s.slice(-err.length), err);
     14        assertEq(s.slice(-(err.length + expected.length), -err.length), expected);
     15    }
     16    if (!failed)
     17        throw new Error("didn't fail");
     18 }
     19 ieval = eval;
     20 function check(expr, expected=expr, testStrict=true) {
     21    var end, err;
     22    for ([end, err] of [[".random_prop", " is undefined"], ["()", " is not a function"]]) {
     23        var statement = "o = {};" + expr + end, f;
     24        var cases = [
     25            // Global scope
     26            function () {
     27                ieval("var o, undef;\n" + statement);
     28            },
     29            // Function scope
     30            Function("o", "undef", statement),
     31            // Function scope with variables
     32            Function("var o, undef;\n" + statement),
     33            // Function scope with some different arugments
     34            Function("arg1", "arg2", "var o, undef;\n" + statement),
     35            // Deoptimized function scope
     36            Function("o", "undef", "with (Object) {}\n" + statement),
     37            // Inside with
     38            Function("with (Object) { " + statement + " }"),
     39            // Closure
     40            Function("o", "undef", "function myfunc() { return o + undef; }\n" + statement),
     41            // Let definitions in a block
     42            Function("{ let o, undef;\n" + statement + "}"),
     43            // Let in a switch
     44            Function("var x = 4; switch (x) { case 4: let o, undef;" + statement + "\ncase 6: break;}"),
     45            // Try-catch blocks
     46            Function("o", "undef", "try { let q = 4; try { let p = 4; } catch (e) {} } catch (e) {} { let o, undef; " + statement + " }"),
     47            // Let in for-in (uses with to prevent jit compilation: bug 942804, bug 831120 and bug 1041586)
     48            Function("with ({}) {} var undef, o; for (let z in [1, 2]) { " + statement + " }"),
     49        ];
     50 
     51        if (testStrict) {
     52            // Strict mode.
     53            cases.push(Function("o", "undef", "\"use strict\";\n" + statement));
     54        }
     55 
     56        for (var f of cases) {
     57            check_one(expected, f, err);
     58        }
     59    }
     60 }
     61 
     62 check("undef");
     63 check("o.b");
     64 check("o.length");
     65 check("o[true]");
     66 check("o[false]");
     67 check("o[null]");
     68 check("o[0]");
     69 check("o[1]");
     70 check("o[3]");
     71 check("o[256]");
     72 check("o[65536]");
     73 check("o[268435455]");
     74 check("o['1.1']");
     75 check("o[4 + 'h']", "o['4h']");
     76 check("ieval(undef)", "ieval(...)");
     77 check("ieval.call()", "ieval.call()");
     78 check("ieval(...[])", "ieval(...)");
     79 check("ieval(...[undef])", "ieval(...)");
     80 check("ieval(...[undef, undef])", "ieval(...)");
     81 check("(o[0] = 4).foo", "o[0].foo");
     82 // NOTE: This one produces different output in strict mode since "this" is
     83 // undefined in that case.
     84 check("this.x", "this.x", false);
     85 
     86 for (let tok of ["|", "^", "&", "==", "!==", "===", "!==", "<", "<=", ">", ">=",
     87                 ">>", "<<", ">>>", "+", "-", "*", "/", "%"]) {
     88    check("o[(undef " + tok + " 4)]");
     89 }
     90 
     91 check("o[(!o)]");
     92 check("o[(~o)]");
     93 check("o[(+ o)]");
     94 check("o[(- o)]");
     95 
     96 check("o[(!(o + 1))]");
     97 check("o[(~(o + 1))]");
     98 check("o[(+ (o + 1))]");
     99 check("o[(- (o + 1))]");
    100 
    101 // A few one off tests
    102 check_one("6", (function () { 6() }), " is not a function");
    103 check_one("4", (function() { (4||eval)(); }), " is not a function");
    104 check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
    105 check_one("[...][Symbol.iterator]().next().value",
    106          function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
    107 check_one("(void 1)", function() { (void 1)(); }, " is not a function");
    108 check_one("(void o[1])", function() { var o = []; (void o[1])() }, " is not a function");
    109 
    110 check_one("(typeof 1)", function() { (typeof 1)(); }, " is not a function");
    111 check_one("(typeof o[1])", function() { var o = []; (typeof o[1])() }, " is not a function");
    112 
    113 check_one("(delete foo)",
    114          function() { (delete foo)(); },
    115          " is not a function");
    116 check_one("(delete obj.foo)",
    117          function() { var obj = {}; (delete obj.foo)(); },
    118          " is not a function");
    119 check_one("(delete obj.foo)",
    120          function() { "use strict"; var obj = {}; (delete obj.foo)(); },
    121          " is not a function");
    122 check_one("(delete obj[y])",
    123          function() { var obj = {}, y = {}; (delete obj[y])(); },
    124          " is not a function");
    125 check_one("(delete obj[y])",
    126          function() { "use strict"; var obj = {}, y = {}; (delete obj[y])(); },
    127          " is not a function");
    128 
    129 check_one("foo.apply()",
    130          function() { function foo() {} foo.apply()(); },
    131          " is not a function");
    132 
    133 check_one("super()",
    134          function() {
    135            class X extends Object {
    136              constructor() {
    137                super()();
    138              }
    139            }
    140            new X();
    141          },
    142          " is not a function");
    143 check_one("super(...)",
    144          function() {
    145            class X extends Object {
    146              constructor() {
    147                super(...[])();
    148              }
    149            }
    150            new X();
    151          },
    152          " is not a function");
    153 
    154 check_one("super.a",
    155          function() {
    156            class X extends Object {
    157              test() {
    158                super.a();
    159              }
    160            }
    161            var x = new X();
    162            x.test();
    163          },
    164          " is not a function");
    165 
    166 check_one("super[a]",
    167          function() {
    168            var a = "a";
    169            class X extends Object {
    170              test() {
    171                super[a]();
    172              }
    173            }
    174            var x = new X();
    175            x.test();
    176          },
    177          " is not a function");
    178 
    179 check_one("super.a()",
    180          function() {
    181            class Y {
    182              a() {
    183                return 5;
    184              }
    185            }
    186 
    187            class X extends Y {
    188              test() {
    189                super.a()();
    190              }
    191            }
    192 
    193            var x = new X();
    194            x.test();
    195          },
    196          " is not a function");
    197 
    198 check_one("super[a]()",
    199          function() {
    200            class Y {
    201              a() {
    202                return 5;
    203              }
    204            }
    205 
    206            var a = "a";
    207            class X extends Y {
    208              test() {
    209                super[a]()();
    210              }
    211            }
    212 
    213            var x = new X();
    214            x.test();
    215          },
    216          " is not a function");
    217 
    218 check_one("super[1]",
    219          function() {
    220            class X extends Object {
    221              foo() {
    222                return super[1]();
    223              }
    224            }
    225            new X().foo();
    226          },
    227          " is not a function");
    228 
    229 check_one("eval(...)",
    230          function() { eval("")(); },
    231          " is not a function");
    232 check_one("eval(...)",
    233          function() { "use strict"; eval("")(); },
    234          " is not a function");
    235 check_one("eval(...)",
    236          function() { eval(...[""])(); },
    237          " is not a function");
    238 check_one("eval(...)",
    239          function() { "use strict"; eval(...[""])(); },
    240          " is not a function");
    241 
    242 check_one("(new foo())",
    243          function() { function foo() {}; new foo()(); },
    244          " is not a function");
    245 check_one("(new foo(...))",
    246          function() { function foo() {}; new foo(...[])(); },
    247          " is not a function");
    248 check_one("(new foo.x())",
    249          function() { var foo = { x: function() {} }; new foo.x()(); },
    250          " is not a function");
    251 check_one("(new foo.x(...))",
    252          function() { var foo = { x: function() {} }; new foo.x(...[])(); },
    253          " is not a function");
    254 
    255 check_one("[...].foo",
    256          function() { [undefined].foo(); },
    257          " is not a function");
    258 check_one("[...].foo",
    259          function() { [undefined, ...[]].foo(); },
    260          " is not a function");
    261 
    262 check_one("[...][Symbol.iterator]().next().value",
    263          function () { var [{x}] = [null, {}]; }, " is null");
    264 check_one("[...][Symbol.iterator]().next().value",
    265          function () { var [{x}] = [void 0, {}]; }, " is undefined");
    266 
    267 check_one("(a += b)",
    268    function() { var a, b; (a += b)(); },
    269    " is not a function");
    270 
    271 try {
    272  (function() {
    273    "use strict";
    274    var o = [];
    275    Object.freeze(o);
    276    o[0] = "foo";
    277  }());
    278  throw new Error("didn't throw");
    279 } catch (e) {
    280  assertEq(e instanceof TypeError, true,
    281           "expected TypeError, got " + e);
    282  assertEq(e.message,
    283           "can't define array index property past the end of an array with non-writable length");
    284 }
    285 
    286 // Check fallback behavior
    287 assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError);