| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1 | // Copyright 2014 the V8 project authors. All rights reserved. | 
 | 2 | // Use of this source code is governed by a BSD-style license that can be | 
 | 3 | // found in the LICENSE file. | 
 | 4 |  | 
 | 5 | var global = this; | 
 | 6 | var globalProto = Object.getPrototypeOf(global); | 
 | 7 |  | 
 | 8 | // Number of objects being tested. There is an assert ensuring this is correct. | 
 | 9 | var objectCount = 21; | 
 | 10 |  | 
 | 11 |  | 
 | 12 | function runTest(f) { | 
 | 13 |   function restore(object, oldProto) { | 
 | 14 |     delete object[Symbol.unscopables]; | 
 | 15 |     delete object.x; | 
 | 16 |     delete object.x_; | 
 | 17 |     delete object.y; | 
 | 18 |     delete object.z; | 
 | 19 |     Object.setPrototypeOf(object, oldProto); | 
 | 20 |   } | 
 | 21 |  | 
 | 22 |   function getObject(i) { | 
 | 23 |     var objects = [ | 
 | 24 |       {}, | 
 | 25 |       [], | 
 | 26 |       function() {}, | 
 | 27 |       function() { | 
 | 28 |         return arguments; | 
 | 29 |       }(), | 
 | 30 |       function() { | 
 | 31 |         'use strict'; | 
 | 32 |         return arguments; | 
 | 33 |       }(), | 
 | 34 |       Object(1), | 
 | 35 |       Object(true), | 
 | 36 |       Object('bla'), | 
 | 37 |       new Date, | 
 | 38 |       new RegExp, | 
 | 39 |       new Set, | 
 | 40 |       new Map, | 
 | 41 |       new WeakMap, | 
 | 42 |       new WeakSet, | 
 | 43 |       new ArrayBuffer(10), | 
 | 44 |       new Int32Array(5), | 
 | 45 |       Object, | 
 | 46 |       Function, | 
 | 47 |       Date, | 
 | 48 |       RegExp, | 
 | 49 |       global | 
 | 50 |     ]; | 
 | 51 |  | 
 | 52 |     assertEquals(objectCount, objects.length); | 
 | 53 |     return objects[i]; | 
 | 54 |   } | 
 | 55 |  | 
 | 56 |   // Tests depends on this not being there to start with. | 
 | 57 |   delete Array.prototype[Symbol.unscopables]; | 
 | 58 |  | 
 | 59 |   if (f.length === 1) { | 
 | 60 |     for (var i = 0; i < objectCount; i++) { | 
 | 61 |       var object = getObject(i); | 
 | 62 |       var oldObjectProto = Object.getPrototypeOf(object); | 
 | 63 |       f(object); | 
 | 64 |       restore(object, oldObjectProto); | 
 | 65 |     } | 
 | 66 |   } else { | 
 | 67 |     for (var i = 0; i < objectCount; i++) { | 
 | 68 |       for (var j = 0; j < objectCount; j++) { | 
 | 69 |         var object = getObject(i); | 
 | 70 |         var proto = getObject(j); | 
 | 71 |         if (object === proto) { | 
 | 72 |           continue; | 
 | 73 |         } | 
 | 74 |         var oldObjectProto = Object.getPrototypeOf(object); | 
 | 75 |         var oldProtoProto = Object.getPrototypeOf(proto); | 
 | 76 |         f(object, proto); | 
 | 77 |         restore(object, oldObjectProto); | 
 | 78 |         restore(proto, oldProtoProto); | 
 | 79 |       } | 
 | 80 |     } | 
 | 81 |   } | 
 | 82 | } | 
 | 83 |  | 
 | 84 | // Test array first, since other tests are changing | 
 | 85 | // Array.prototype[Symbol.unscopables]. | 
 | 86 | function TestArrayPrototypeUnscopables() { | 
 | 87 |   var descr = Object.getOwnPropertyDescriptor(Array.prototype, | 
 | 88 |                                               Symbol.unscopables); | 
 | 89 |   assertFalse(descr.enumerable); | 
 | 90 |   assertFalse(descr.writable); | 
 | 91 |   assertTrue(descr.configurable); | 
 | 92 |   assertEquals(null, Object.getPrototypeOf(descr.value)); | 
 | 93 |  | 
 | 94 |   var copyWithin = 'local copyWithin'; | 
 | 95 |   var entries = 'local entries'; | 
 | 96 |   var fill = 'local fill'; | 
 | 97 |   var find = 'local find'; | 
 | 98 |   var findIndex = 'local findIndex'; | 
 | 99 |   var keys = 'local keys'; | 
 | 100 |   var values = 'local values'; | 
 | 101 |  | 
 | 102 |   var array = []; | 
 | 103 |   array.toString = 42; | 
 | 104 |  | 
 | 105 |   with (array) { | 
 | 106 |     assertEquals('local copyWithin', copyWithin); | 
 | 107 |     assertEquals('local entries', entries); | 
 | 108 |     assertEquals('local fill', fill); | 
 | 109 |     assertEquals('local find', find); | 
 | 110 |     assertEquals('local findIndex', findIndex); | 
 | 111 |     assertEquals('local keys', keys); | 
 | 112 |     assertEquals('local values', values); | 
 | 113 |     assertEquals(42, toString); | 
 | 114 |   } | 
 | 115 | } | 
 | 116 | TestArrayPrototypeUnscopables(); | 
 | 117 |  | 
 | 118 |  | 
 | 119 |  | 
 | 120 | function TestBasics(object) { | 
 | 121 |   var x = 1; | 
 | 122 |   var y = 2; | 
 | 123 |   var z = 3; | 
 | 124 |   object.x = 4; | 
 | 125 |   object.y = 5; | 
 | 126 |  | 
 | 127 |   with (object) { | 
 | 128 |     assertEquals(4, x); | 
 | 129 |     assertEquals(5, y); | 
 | 130 |     assertEquals(3, z); | 
 | 131 |   } | 
 | 132 |  | 
 | 133 |   object[Symbol.unscopables] = {x: true}; | 
 | 134 |   with (object) { | 
 | 135 |     assertEquals(1, x); | 
 | 136 |     assertEquals(5, y); | 
 | 137 |     assertEquals(3, z); | 
 | 138 |   } | 
 | 139 |  | 
 | 140 |   object[Symbol.unscopables] = {x: 0, y: true}; | 
 | 141 |   with (object) { | 
 | 142 |     assertEquals(1, x); | 
 | 143 |     assertEquals(2, y); | 
 | 144 |     assertEquals(3, z); | 
 | 145 |   } | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 146 |  | 
 | 147 |   object[Symbol.unscopables] = {x: 0, y: undefined}; | 
 | 148 |   with (object) { | 
 | 149 |     assertEquals(1, x); | 
 | 150 |     assertEquals(5, y); | 
 | 151 |     assertEquals(3, z); | 
 | 152 |   } | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 153 | } | 
 | 154 | runTest(TestBasics); | 
 | 155 |  | 
 | 156 |  | 
 | 157 | function TestUnscopableChain(object) { | 
 | 158 |   var x = 1; | 
 | 159 |   object.x = 2; | 
 | 160 |  | 
 | 161 |   with (object) { | 
 | 162 |     assertEquals(2, x); | 
 | 163 |   } | 
 | 164 |  | 
 | 165 |   object[Symbol.unscopables] = { | 
 | 166 |     __proto__: {x: true} | 
 | 167 |   }; | 
 | 168 |   with (object) { | 
 | 169 |     assertEquals(1, x); | 
 | 170 |   } | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 171 |  | 
 | 172 |   object[Symbol.unscopables] = { | 
 | 173 |     __proto__: {x: undefined} | 
 | 174 |   }; | 
 | 175 |   with (object) { | 
 | 176 |     assertEquals(2, x); | 
 | 177 |   } | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 178 | } | 
 | 179 | runTest(TestUnscopableChain); | 
 | 180 |  | 
 | 181 |  | 
 | 182 | function TestBasicsSet(object) { | 
 | 183 |   var x = 1; | 
 | 184 |   object.x = 2; | 
 | 185 |  | 
 | 186 |   with (object) { | 
 | 187 |     assertEquals(2, x); | 
 | 188 |   } | 
 | 189 |  | 
 | 190 |   object[Symbol.unscopables] = {x: true}; | 
 | 191 |   with (object) { | 
 | 192 |     assertEquals(1, x); | 
 | 193 |     x = 3; | 
 | 194 |     assertEquals(3, x); | 
 | 195 |   } | 
 | 196 |  | 
 | 197 |   assertEquals(3, x); | 
 | 198 |   assertEquals(2, object.x); | 
 | 199 | } | 
 | 200 | runTest(TestBasicsSet); | 
 | 201 |  | 
 | 202 |  | 
 | 203 | function TestOnProto(object, proto) { | 
 | 204 |   var x = 1; | 
 | 205 |   var y = 2; | 
 | 206 |   var z = 3; | 
 | 207 |   proto.x = 4; | 
 | 208 |  | 
 | 209 |   Object.setPrototypeOf(object, proto); | 
 | 210 |   object.y = 5; | 
 | 211 |  | 
 | 212 |   with (object) { | 
 | 213 |     assertEquals(4, x); | 
 | 214 |     assertEquals(5, y); | 
 | 215 |     assertEquals(3, z); | 
 | 216 |   } | 
 | 217 |  | 
 | 218 |   proto[Symbol.unscopables] = {x: true}; | 
 | 219 |   with (object) { | 
 | 220 |     assertEquals(1, x); | 
 | 221 |     assertEquals(5, y); | 
 | 222 |     assertEquals(3, z); | 
 | 223 |   } | 
 | 224 |  | 
 | 225 |   object[Symbol.unscopables] = {y: true}; | 
 | 226 |   with (object) { | 
 | 227 |     assertEquals(4, x); | 
 | 228 |     assertEquals(2, y); | 
 | 229 |     assertEquals(3, z); | 
 | 230 |   } | 
 | 231 |  | 
 | 232 |   proto[Symbol.unscopables] = {y: true}; | 
 | 233 |   object[Symbol.unscopables] = {x: true}; | 
 | 234 |   with (object) { | 
 | 235 |     assertEquals(1, x); | 
 | 236 |     assertEquals(5, y); | 
 | 237 |     assertEquals(3, z); | 
 | 238 |   } | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 239 |  | 
 | 240 |   proto[Symbol.unscopables] = {y: true}; | 
 | 241 |   object[Symbol.unscopables] = {x: true, y: undefined}; | 
 | 242 |   with (object) { | 
 | 243 |     assertEquals(1, x); | 
 | 244 |     assertEquals(5, y); | 
 | 245 |     assertEquals(3, z); | 
 | 246 |   } | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 247 | } | 
 | 248 | runTest(TestOnProto); | 
 | 249 |  | 
 | 250 |  | 
 | 251 | function TestSetBlockedOnProto(object, proto) { | 
 | 252 |   var x = 1; | 
 | 253 |   object.x = 2; | 
 | 254 |  | 
 | 255 |   with (object) { | 
 | 256 |     assertEquals(2, x); | 
 | 257 |   } | 
 | 258 |  | 
 | 259 |   Object.setPrototypeOf(object, proto); | 
 | 260 |   proto[Symbol.unscopables] = {x: true}; | 
 | 261 |   with (object) { | 
 | 262 |     assertEquals(1, x); | 
 | 263 |     x = 3; | 
 | 264 |     assertEquals(3, x); | 
 | 265 |   } | 
 | 266 |  | 
 | 267 |   assertEquals(3, x); | 
 | 268 |   assertEquals(2, object.x); | 
 | 269 | } | 
 | 270 | runTest(TestSetBlockedOnProto); | 
 | 271 |  | 
 | 272 |  | 
 | 273 | function TestNonObject(object) { | 
 | 274 |   var x = 1; | 
 | 275 |   var y = 2; | 
 | 276 |   object.x = 3; | 
 | 277 |   object.y = 4; | 
 | 278 |  | 
 | 279 |   object[Symbol.unscopables] = 'xy'; | 
 | 280 |   with (object) { | 
 | 281 |     assertEquals(3, x); | 
 | 282 |     assertEquals(4, y); | 
 | 283 |   } | 
 | 284 |  | 
 | 285 |   object[Symbol.unscopables] = null; | 
 | 286 |   with (object) { | 
 | 287 |     assertEquals(3, x); | 
 | 288 |     assertEquals(4, y); | 
 | 289 |   } | 
 | 290 | } | 
 | 291 | runTest(TestNonObject); | 
 | 292 |  | 
 | 293 |  | 
 | 294 | function TestChangeDuringWith(object) { | 
 | 295 |   var x = 1; | 
 | 296 |   var y = 2; | 
 | 297 |   object.x = 3; | 
 | 298 |   object.y = 4; | 
 | 299 |  | 
 | 300 |   with (object) { | 
 | 301 |     assertEquals(3, x); | 
 | 302 |     assertEquals(4, y); | 
 | 303 |     object[Symbol.unscopables] = {x: true}; | 
 | 304 |     assertEquals(1, x); | 
 | 305 |     assertEquals(4, y); | 
 | 306 |   } | 
 | 307 | } | 
 | 308 | runTest(TestChangeDuringWith); | 
 | 309 |  | 
 | 310 |  | 
 | 311 | function TestChangeDuringWithWithPossibleOptimization(object) { | 
 | 312 |   var x = 1; | 
 | 313 |   object.x = 2; | 
 | 314 |   with (object) { | 
 | 315 |     for (var i = 0; i < 1000; i++) { | 
 | 316 |       if (i === 500) object[Symbol.unscopables] = {x: true}; | 
 | 317 |       assertEquals(i < 500 ? 2: 1, x); | 
 | 318 |     } | 
 | 319 |   } | 
 | 320 | } | 
 | 321 | TestChangeDuringWithWithPossibleOptimization({}); | 
 | 322 |  | 
 | 323 |  | 
 | 324 | function TestChangeDuringWithWithPossibleOptimization2(object) { | 
 | 325 |   var x = 1; | 
 | 326 |   object.x = 2; | 
 | 327 |   object[Symbol.unscopables] = {x: true}; | 
 | 328 |   with (object) { | 
 | 329 |     for (var i = 0; i < 1000; i++) { | 
 | 330 |       if (i === 500) delete object[Symbol.unscopables]; | 
 | 331 |       assertEquals(i < 500 ? 1 : 2, x); | 
 | 332 |     } | 
 | 333 |   } | 
 | 334 | } | 
 | 335 | TestChangeDuringWithWithPossibleOptimization2({}); | 
 | 336 |  | 
 | 337 |  | 
 | 338 | function TestChangeDuringWithWithPossibleOptimization3(object) { | 
 | 339 |   var x = 1; | 
 | 340 |   object.x = 2; | 
 | 341 |   object[Symbol.unscopables] = {}; | 
 | 342 |   with (object) { | 
 | 343 |     for (var i = 0; i < 1000; i++) { | 
 | 344 |       if (i === 500) object[Symbol.unscopables].x = true; | 
 | 345 |       assertEquals(i < 500 ? 2 : 1, x); | 
 | 346 |     } | 
 | 347 |   } | 
 | 348 | } | 
 | 349 | TestChangeDuringWithWithPossibleOptimization3({}); | 
 | 350 |  | 
 | 351 |  | 
 | 352 | function TestChangeDuringWithWithPossibleOptimization4(object) { | 
 | 353 |   var x = 1; | 
 | 354 |   object.x = 2; | 
 | 355 |   object[Symbol.unscopables] = {x: true}; | 
 | 356 |   with (object) { | 
 | 357 |     for (var i = 0; i < 1000; i++) { | 
 | 358 |       if (i === 500) delete object[Symbol.unscopables].x; | 
 | 359 |       assertEquals(i < 500 ? 1 : 2, x); | 
 | 360 |     } | 
 | 361 |   } | 
 | 362 | } | 
 | 363 | TestChangeDuringWithWithPossibleOptimization4({}); | 
 | 364 |  | 
 | 365 |  | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 366 | function TestChangeDuringWithWithPossibleOptimization4(object) { | 
 | 367 |   var x = 1; | 
 | 368 |   object.x = 2; | 
 | 369 |   object[Symbol.unscopables] = {x: true}; | 
 | 370 |   with (object) { | 
 | 371 |     for (var i = 0; i < 1000; i++) { | 
 | 372 |       if (i === 500) object[Symbol.unscopables].x = undefined; | 
 | 373 |       assertEquals(i < 500 ? 1 : 2, x); | 
 | 374 |     } | 
 | 375 |   } | 
 | 376 | } | 
 | 377 | TestChangeDuringWithWithPossibleOptimization4({}); | 
 | 378 |  | 
 | 379 |  | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 380 | function TestAccessorReceiver(object, proto) { | 
 | 381 |   var x = 'local'; | 
 | 382 |  | 
 | 383 |   Object.defineProperty(proto, 'x', { | 
 | 384 |     get: function() { | 
 | 385 |       assertEquals(object, this); | 
 | 386 |       return this.x_; | 
 | 387 |     }, | 
 | 388 |     configurable: true | 
 | 389 |   }); | 
 | 390 |   proto.x_ = 'proto'; | 
 | 391 |  | 
 | 392 |   Object.setPrototypeOf(object, proto); | 
 | 393 |   proto.x_ = 'object'; | 
 | 394 |  | 
 | 395 |   with (object) { | 
 | 396 |     assertEquals('object', x); | 
 | 397 |   } | 
 | 398 | } | 
 | 399 | runTest(TestAccessorReceiver); | 
 | 400 |  | 
 | 401 |  | 
 | 402 | function TestUnscopablesGetter(object) { | 
 | 403 |   // This test gets really messy when object is the global since the assert | 
 | 404 |   // functions are properties on the global object and the call count gets | 
 | 405 |   // completely different. | 
 | 406 |   if (object === global) return; | 
 | 407 |  | 
 | 408 |   var x = 'local'; | 
 | 409 |   object.x = 'object'; | 
 | 410 |  | 
 | 411 |   var callCount = 0; | 
 | 412 |   Object.defineProperty(object, Symbol.unscopables, { | 
 | 413 |     get: function() { | 
 | 414 |       callCount++; | 
 | 415 |       return {}; | 
 | 416 |     }, | 
 | 417 |     configurable: true | 
 | 418 |   }); | 
 | 419 |   with (object) { | 
 | 420 |     assertEquals('object', x); | 
 | 421 |   } | 
 | 422 |   // Once for HasBinding | 
 | 423 |   assertEquals(1, callCount); | 
 | 424 |  | 
 | 425 |   callCount = 0; | 
 | 426 |   Object.defineProperty(object, Symbol.unscopables, { | 
 | 427 |     get: function() { | 
 | 428 |       callCount++; | 
 | 429 |       return {x: true}; | 
 | 430 |     }, | 
 | 431 |     configurable: true | 
 | 432 |   }); | 
 | 433 |   with (object) { | 
 | 434 |     assertEquals('local', x); | 
 | 435 |   } | 
 | 436 |   // Once for HasBinding | 
 | 437 |   assertEquals(1, callCount); | 
 | 438 |  | 
 | 439 |   callCount = 0; | 
 | 440 |   Object.defineProperty(object, Symbol.unscopables, { | 
 | 441 |     get: function() { | 
 | 442 |       callCount++; | 
 | 443 |       return callCount == 1 ? {} : {x: true}; | 
 | 444 |     }, | 
 | 445 |     configurable: true | 
 | 446 |   }); | 
 | 447 |   with (object) { | 
 | 448 |     x = 1; | 
 | 449 |   } | 
 | 450 |   // Once for HasBinding | 
 | 451 |   assertEquals(1, callCount); | 
 | 452 |   assertEquals(1, object.x); | 
 | 453 |   assertEquals('local', x); | 
 | 454 |   with (object) { | 
 | 455 |     x = 2; | 
 | 456 |   } | 
 | 457 |   // One more HasBinding. | 
 | 458 |   assertEquals(2, callCount); | 
 | 459 |   assertEquals(1, object.x); | 
 | 460 |   assertEquals(2, x); | 
 | 461 | } | 
 | 462 | runTest(TestUnscopablesGetter); | 
 | 463 |  | 
 | 464 |  | 
 | 465 | var global = this; | 
 | 466 | function TestUnscopablesGetter2() { | 
 | 467 |   var x = 'local'; | 
 | 468 |  | 
 | 469 |   var globalProto = Object.getPrototypeOf(global); | 
 | 470 |   var protos = [{}, [], function() {}, global]; | 
 | 471 |   var objects = [{}, [], function() {}]; | 
 | 472 |  | 
 | 473 |   protos.forEach(function(proto) { | 
 | 474 |     objects.forEach(function(object) { | 
 | 475 |       Object.defineProperty(proto, 'x', { | 
 | 476 |         get: function() { | 
 | 477 |           assertEquals(object, this); | 
 | 478 |           return 'proto'; | 
 | 479 |         }, | 
 | 480 |         configurable: true | 
 | 481 |       }); | 
 | 482 |  | 
 | 483 |       object.__proto__ = proto; | 
 | 484 |       Object.defineProperty(object, 'x', { | 
 | 485 |         get: function() { | 
 | 486 |           assertEquals(object, this); | 
 | 487 |           return 'object'; | 
 | 488 |         }, | 
 | 489 |         configurable: true | 
 | 490 |       }); | 
 | 491 |  | 
 | 492 |       with (object) { | 
 | 493 |         assertEquals('object', x); | 
 | 494 |       } | 
 | 495 |  | 
 | 496 |       object[Symbol.unscopables] = {x: true}; | 
 | 497 |       with (object) { | 
 | 498 |         assertEquals('local', x); | 
 | 499 |       } | 
 | 500 |  | 
 | 501 |       delete proto[Symbol.unscopables]; | 
 | 502 |       delete object[Symbol.unscopables]; | 
 | 503 |     }); | 
 | 504 |   }); | 
 | 505 |  | 
 | 506 |   delete global.x; | 
 | 507 |   Object.setPrototypeOf(global, globalProto); | 
 | 508 | } | 
 | 509 | TestUnscopablesGetter2(); | 
 | 510 |  | 
 | 511 |  | 
 | 512 | function TestSetterOnBlacklisted(object, proto) { | 
 | 513 |   var x = 'local'; | 
 | 514 |   Object.defineProperty(proto, 'x', { | 
 | 515 |     set: function(x) { | 
 | 516 |       assertUnreachable(); | 
 | 517 |     }, | 
 | 518 |     get: function() { | 
 | 519 |       return 'proto'; | 
 | 520 |     }, | 
 | 521 |     configurable: true | 
 | 522 |   }); | 
 | 523 |   Object.setPrototypeOf(object, proto); | 
 | 524 |   Object.defineProperty(object, 'x', { | 
 | 525 |     get: function() { | 
 | 526 |       return this.x_; | 
 | 527 |     }, | 
 | 528 |     set: function(x) { | 
 | 529 |       this.x_ = x; | 
 | 530 |     }, | 
 | 531 |     configurable: true | 
 | 532 |   }); | 
 | 533 |   object.x_ = 1; | 
 | 534 |  | 
 | 535 |   with (object) { | 
 | 536 |     x = 2; | 
 | 537 |     assertEquals(2, x); | 
 | 538 |   } | 
 | 539 |  | 
 | 540 |   assertEquals(2, object.x); | 
 | 541 |  | 
 | 542 |   object[Symbol.unscopables] = {x: true}; | 
 | 543 |  | 
 | 544 |   with (object) { | 
 | 545 |     x = 3; | 
 | 546 |     assertEquals(3, x); | 
 | 547 |   } | 
 | 548 |  | 
 | 549 |   assertEquals(2, object.x); | 
 | 550 | } | 
 | 551 | runTest(TestSetterOnBlacklisted); | 
 | 552 |  | 
 | 553 |  | 
 | 554 | function TestObjectsAsUnscopables(object, unscopables) { | 
 | 555 |   var x = 1; | 
 | 556 |   object.x = 2; | 
 | 557 |  | 
 | 558 |   with (object) { | 
 | 559 |     assertEquals(2, x); | 
 | 560 |     object[Symbol.unscopables] = unscopables; | 
 | 561 |     assertEquals(2, x); | 
 | 562 |   } | 
 | 563 | } | 
 | 564 | runTest(TestObjectsAsUnscopables); | 
 | 565 |  | 
 | 566 |  | 
 | 567 | function TestAccessorOnUnscopables(object) { | 
 | 568 |   var x = 1; | 
 | 569 |   object.x = 2; | 
 | 570 |  | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 571 |   var calls = 0; | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 572 |   var unscopables = { | 
 | 573 |     get x() { | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 574 |       calls++; | 
 | 575 |       return calls === 1 ? true : undefined; | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 576 |     } | 
 | 577 |   }; | 
 | 578 |  | 
 | 579 |   with (object) { | 
 | 580 |     assertEquals(2, x); | 
 | 581 |     object[Symbol.unscopables] = unscopables; | 
 | 582 |     assertEquals(1, x); | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 583 |     assertEquals(2, x); | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 584 |   } | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 585 |   assertEquals(2, calls); | 
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 586 | } | 
 | 587 | runTest(TestAccessorOnUnscopables); | 
 | 588 |  | 
 | 589 |  | 
 | 590 | function TestLengthUnscopables(object, proto) { | 
 | 591 |   var length = 2; | 
 | 592 |   with (object) { | 
 | 593 |     assertEquals(1, length); | 
 | 594 |     object[Symbol.unscopables] = {length: true}; | 
 | 595 |     assertEquals(2, length); | 
 | 596 |     delete object[Symbol.unscopables]; | 
 | 597 |     assertEquals(1, length); | 
 | 598 |   } | 
 | 599 | } | 
 | 600 | TestLengthUnscopables([1], Array.prototype); | 
 | 601 | TestLengthUnscopables(function(x) {}, Function.prototype); | 
 | 602 | TestLengthUnscopables(new String('x'), String.prototype); | 
 | 603 |  | 
 | 604 |  | 
 | 605 | function TestFunctionNameUnscopables(object) { | 
 | 606 |   var name = 'local'; | 
 | 607 |   with (object) { | 
 | 608 |     assertEquals('f', name); | 
 | 609 |     object[Symbol.unscopables] = {name: true}; | 
 | 610 |     assertEquals('local', name); | 
 | 611 |     delete object[Symbol.unscopables]; | 
 | 612 |     assertEquals('f', name); | 
 | 613 |   } | 
 | 614 | } | 
 | 615 | TestFunctionNameUnscopables(function f() {}); | 
 | 616 |  | 
 | 617 |  | 
 | 618 | function TestFunctionPrototypeUnscopables() { | 
 | 619 |   var prototype = 'local'; | 
 | 620 |   var f = function() {}; | 
 | 621 |   var g = function() {}; | 
 | 622 |   Object.setPrototypeOf(f, g); | 
 | 623 |   var fp = f.prototype; | 
 | 624 |   var gp = g.prototype; | 
 | 625 |   with (f) { | 
 | 626 |     assertEquals(fp, prototype); | 
 | 627 |     f[Symbol.unscopables] = {prototype: true}; | 
 | 628 |     assertEquals('local', prototype); | 
 | 629 |     delete f[Symbol.unscopables]; | 
 | 630 |     assertEquals(fp, prototype); | 
 | 631 |   } | 
 | 632 | } | 
 | 633 | TestFunctionPrototypeUnscopables(function() {}); | 
 | 634 |  | 
 | 635 |  | 
 | 636 | function TestFunctionArgumentsUnscopables() { | 
 | 637 |   var func = function() { | 
 | 638 |     var arguments = 'local'; | 
 | 639 |     var args = func.arguments; | 
 | 640 |     with (func) { | 
 | 641 |       assertEquals(args, arguments); | 
 | 642 |       func[Symbol.unscopables] = {arguments: true}; | 
 | 643 |       assertEquals('local', arguments); | 
 | 644 |       delete func[Symbol.unscopables]; | 
 | 645 |       assertEquals(args, arguments); | 
 | 646 |     } | 
 | 647 |   } | 
 | 648 |   func(1); | 
 | 649 | } | 
 | 650 | TestFunctionArgumentsUnscopables(); | 
 | 651 |  | 
 | 652 |  | 
 | 653 | function TestArgumentsLengthUnscopables() { | 
 | 654 |   var func = function() { | 
 | 655 |     var length = 'local'; | 
 | 656 |     with (arguments) { | 
 | 657 |       assertEquals(1, length); | 
 | 658 |       arguments[Symbol.unscopables] = {length: true}; | 
 | 659 |       assertEquals('local', length); | 
 | 660 |     } | 
 | 661 |   } | 
 | 662 |   func(1); | 
 | 663 | } | 
 | 664 | TestArgumentsLengthUnscopables(); | 
 | 665 |  | 
 | 666 |  | 
 | 667 | function TestFunctionCallerUnscopables() { | 
 | 668 |   var func = function() { | 
 | 669 |     var caller = 'local'; | 
 | 670 |     with (func) { | 
 | 671 |       assertEquals(TestFunctionCallerUnscopables, caller); | 
 | 672 |       func[Symbol.unscopables] = {caller: true}; | 
 | 673 |       assertEquals('local', caller); | 
 | 674 |       delete func[Symbol.unscopables]; | 
 | 675 |       assertEquals(TestFunctionCallerUnscopables, caller); | 
 | 676 |     } | 
 | 677 |   } | 
 | 678 |   func(1); | 
 | 679 | } | 
 | 680 | TestFunctionCallerUnscopables(); | 
 | 681 |  | 
 | 682 |  | 
 | 683 | function TestGetUnscopablesGetterThrows() { | 
 | 684 |   var object = { | 
 | 685 |     get x() { | 
 | 686 |       assertUnreachable(); | 
 | 687 |     } | 
 | 688 |   }; | 
 | 689 |   function CustomError() {} | 
 | 690 |   Object.defineProperty(object, Symbol.unscopables, { | 
 | 691 |     get: function() { | 
 | 692 |       throw new CustomError(); | 
 | 693 |     } | 
 | 694 |   }); | 
 | 695 |   assertThrows(function() { | 
 | 696 |     with (object) { | 
 | 697 |       x; | 
 | 698 |     } | 
 | 699 |   }, CustomError); | 
 | 700 | } | 
 | 701 | TestGetUnscopablesGetterThrows(); | 
| Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame^] | 702 |  | 
 | 703 |  | 
 | 704 | function TestGetUnscopablesGetterThrows2() { | 
 | 705 |   var object = { | 
 | 706 |     get x() { | 
 | 707 |       assertUnreachable(); | 
 | 708 |     } | 
 | 709 |   }; | 
 | 710 |   function CustomError() {} | 
 | 711 |  | 
 | 712 |   object[Symbol.unscopables] = { | 
 | 713 |     get x() { | 
 | 714 |       throw new CustomError(); | 
 | 715 |     } | 
 | 716 |   }; | 
 | 717 |   assertThrows(function() { | 
 | 718 |     with (object) { | 
 | 719 |       x; | 
 | 720 |     } | 
 | 721 |   }, CustomError); | 
 | 722 | } | 
 | 723 | TestGetUnscopablesGetterThrows(); |