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);