Home | History | Annotate | Download | only in harmony
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // We change the stack size for the ARM64 simulator because at one point this
     29 // test enters an infinite recursion which goes through the runtime and we
     30 // overflow the system stack before the simulator stack.
     31 
     32 // Flags: --harmony-proxies --sim-stack-size=500
     33 
     34 
     35 // Helper.
     36 
     37 function TestWithProxies(test, x, y, z) {
     38   test(Proxy.create, x, y, z)
     39   test(function(h) {return Proxy.createFunction(h, function() {})}, x, y, z)
     40 }
     41 
     42 
     43 
     44 // Getting property descriptors (Object.getOwnPropertyDescriptor).
     45 
     46 var key
     47 
     48 function TestGetOwnProperty(handler) {
     49   TestWithProxies(TestGetOwnProperty2, handler)
     50 }
     51 
     52 function TestGetOwnProperty2(create, handler) {
     53   var p = create(handler)
     54   assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value)
     55   assertEquals("a", key)
     56   assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value)
     57   assertEquals("99", key)
     58 }
     59 
     60 TestGetOwnProperty({
     61   getOwnPropertyDescriptor: function(k) {
     62     key = k
     63     return {value: 42, configurable: true}
     64   }
     65 })
     66 
     67 TestGetOwnProperty({
     68   getOwnPropertyDescriptor: function(k) {
     69     return this.getOwnPropertyDescriptor2(k)
     70   },
     71   getOwnPropertyDescriptor2: function(k) {
     72     key = k
     73     return {value: 42, configurable: true}
     74   }
     75 })
     76 
     77 TestGetOwnProperty({
     78   getOwnPropertyDescriptor: function(k) {
     79     key = k
     80     return {get value() { return 42 }, get configurable() { return true }}
     81   }
     82 })
     83 
     84 TestGetOwnProperty(Proxy.create({
     85   get: function(pr, pk) {
     86     return function(k) { key = k; return {value: 42, configurable: true} }
     87   }
     88 }))
     89 
     90 
     91 function TestGetOwnPropertyThrow(handler) {
     92   TestWithProxies(TestGetOwnPropertyThrow2, handler)
     93 }
     94 
     95 function TestGetOwnPropertyThrow2(create, handler) {
     96   var p = create(handler)
     97   assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn")
     98   assertThrows(function(){ Object.getOwnPropertyDescriptor(p, 77) }, "myexn")
     99 }
    100 
    101 TestGetOwnPropertyThrow({
    102   getOwnPropertyDescriptor: function(k) { throw "myexn" }
    103 })
    104 
    105 TestGetOwnPropertyThrow({
    106   getOwnPropertyDescriptor: function(k) {
    107     return this.getPropertyDescriptor2(k)
    108   },
    109   getOwnPropertyDescriptor2: function(k) { throw "myexn" }
    110 })
    111 
    112 TestGetOwnPropertyThrow({
    113   getOwnPropertyDescriptor: function(k) {
    114     return {get value() { throw "myexn" }}
    115   }
    116 })
    117 
    118 TestGetOwnPropertyThrow(Proxy.create({
    119   get: function(pr, pk) {
    120     return function(k) { throw "myexn" }
    121   }
    122 }))
    123 
    124 
    125 
    126 // Getters (dot, brackets).
    127 
    128 var key
    129 
    130 function TestGet(handler) {
    131   TestWithProxies(TestGet2, handler)
    132 }
    133 
    134 function TestGet2(create, handler) {
    135   var p = create(handler)
    136   assertEquals(42, p.a)
    137   assertEquals("a", key)
    138   assertEquals(42, p["b"])
    139   assertEquals("b", key)
    140   assertEquals(42, p[99])
    141   assertEquals("99", key)
    142   assertEquals(42, (function(n) { return p[n] })("c"))
    143   assertEquals("c", key)
    144   assertEquals(42, (function(n) { return p[n] })(101))
    145   assertEquals("101", key)
    146 
    147   var o = Object.create(p, {x: {value: 88}})
    148   assertEquals(42, o.a)
    149   assertEquals("a", key)
    150   assertEquals(42, o["b"])
    151   assertEquals("b", key)
    152   assertEquals(42, o[99])
    153   assertEquals("99", key)
    154   assertEquals(88, o.x)
    155   assertEquals(88, o["x"])
    156   assertEquals(42, (function(n) { return o[n] })("c"))
    157   assertEquals("c", key)
    158   assertEquals(42, (function(n) { return o[n] })(101))
    159   assertEquals("101", key)
    160   assertEquals(88, (function(n) { return o[n] })("x"))
    161 }
    162 
    163 TestGet({
    164   get: function(r, k) { key = k; return 42 }
    165 })
    166 
    167 TestGet({
    168   get: function(r, k) { return this.get2(r, k) },
    169   get2: function(r, k) { key = k; return 42 }
    170 })
    171 
    172 TestGet({
    173   getPropertyDescriptor: function(k) { key = k; return {value: 42} }
    174 })
    175 
    176 TestGet({
    177   getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
    178   getPropertyDescriptor2: function(k) { key = k; return {value: 42} }
    179 })
    180 
    181 TestGet({
    182   getPropertyDescriptor: function(k) {
    183     key = k;
    184     return {get value() { return 42 }}
    185   }
    186 })
    187 
    188 TestGet({
    189   get: undefined,
    190   getPropertyDescriptor: function(k) { key = k; return {value: 42} }
    191 })
    192 
    193 TestGet(Proxy.create({
    194   get: function(pr, pk) {
    195     return function(r, k) { key = k; return 42 }
    196   }
    197 }))
    198 
    199 
    200 function TestGetCall(handler) {
    201   TestWithProxies(TestGetCall2, handler)
    202 }
    203 
    204 function TestGetCall2(create, handler) {
    205   var p = create(handler)
    206   assertEquals(55, p.f())
    207   assertEquals(55, p["f"]())
    208   assertEquals(55, p.f("unused", "arguments"))
    209   assertEquals(55, p.f.call(p))
    210   assertEquals(55, p["f"].call(p))
    211   assertEquals(55, p[101].call(p))
    212   assertEquals(55, p.withargs(45, 5))
    213   assertEquals(55, p.withargs.call(p, 11, 22))
    214   assertEquals(55, (function(n) { return p[n]() })("f"))
    215   assertEquals(55, (function(n) { return p[n].call(p) })("f"))
    216   assertEquals(55, (function(n) { return p[n](15, 20) })("withargs"))
    217   assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs"))
    218   assertEquals("6655", "66" + p)  // calls p.toString
    219 
    220   var o = Object.create(p, {g: {value: function(x) { return x + 88 }}})
    221   assertEquals(55, o.f())
    222   assertEquals(55, o["f"]())
    223   assertEquals(55, o.f("unused", "arguments"))
    224   assertEquals(55, o.f.call(o))
    225   assertEquals(55, o.f.call(p))
    226   assertEquals(55, o["f"].call(p))
    227   assertEquals(55, o[101].call(p))
    228   assertEquals(55, o.withargs(45, 5))
    229   assertEquals(55, o.withargs.call(p, 11, 22))
    230   assertEquals(90, o.g(2))
    231   assertEquals(91, o.g.call(o, 3))
    232   assertEquals(92, o.g.call(p, 4))
    233   assertEquals(55, (function(n) { return o[n]() })("f"))
    234   assertEquals(55, (function(n) { return o[n].call(o) })("f"))
    235   assertEquals(55, (function(n) { return o[n](15, 20) })("withargs"))
    236   assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs"))
    237   assertEquals(93, (function(n) { return o[n](5) })("g"))
    238   assertEquals(94, (function(n) { return o[n].call(o, 6) })("g"))
    239   assertEquals(95, (function(n) { return o[n].call(p, 7) })("g"))
    240   assertEquals("6655", "66" + o)  // calls o.toString
    241 }
    242 
    243 TestGetCall({
    244   get: function(r, k) { return function() { return 55 } }
    245 })
    246 
    247 TestGetCall({
    248   get: function(r, k) { return this.get2(r, k) },
    249   get2: function(r, k) { return function() { return 55 } }
    250 })
    251 
    252 TestGetCall({
    253   getPropertyDescriptor: function(k) {
    254     return {value: function() { return 55 }}
    255   }
    256 })
    257 
    258 TestGetCall({
    259   getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
    260   getPropertyDescriptor2: function(k) {
    261     return {value: function() { return 55 }}
    262   }
    263 })
    264 
    265 TestGetCall({
    266   getPropertyDescriptor: function(k) {
    267     return {get value() { return function() { return 55 } }}
    268   }
    269 })
    270 
    271 TestGetCall({
    272   get: undefined,
    273   getPropertyDescriptor: function(k) {
    274     return {value: function() { return 55 }}
    275   }
    276 })
    277 
    278 TestGetCall({
    279   get: function(r, k) {
    280     if (k == "gg") {
    281       return function() { return 55 }
    282     } else if (k == "withargs") {
    283       return function(n, m) { return n + m * 2 }
    284     } else {
    285       return function() { return this.gg() }
    286     }
    287   }
    288 })
    289 
    290 TestGetCall(Proxy.create({
    291   get: function(pr, pk) {
    292     return function(r, k) { return function() { return 55 } }
    293   }
    294 }))
    295 
    296 
    297 function TestGetThrow(handler) {
    298   TestWithProxies(TestGetThrow2, handler)
    299 }
    300 
    301 function TestGetThrow2(create, handler) {
    302   var p = create(handler)
    303   assertThrows(function(){ p.a }, "myexn")
    304   assertThrows(function(){ p["b"] }, "myexn")
    305   assertThrows(function(){ p[3] }, "myexn")
    306   assertThrows(function(){ (function(n) { p[n] })("c") }, "myexn")
    307   assertThrows(function(){ (function(n) { p[n] })(99) }, "myexn")
    308 
    309   var o = Object.create(p, {x: {value: 88}, '4': {value: 89}})
    310   assertThrows(function(){ o.a }, "myexn")
    311   assertThrows(function(){ o["b"] }, "myexn")
    312   assertThrows(function(){ o[3] }, "myexn")
    313   assertThrows(function(){ (function(n) { o[n] })("c") }, "myexn")
    314   assertThrows(function(){ (function(n) { o[n] })(99) }, "myexn")
    315 }
    316 
    317 TestGetThrow({
    318   get: function(r, k) { throw "myexn" }
    319 })
    320 
    321 TestGetThrow({
    322   get: function(r, k) { return this.get2(r, k) },
    323   get2: function(r, k) { throw "myexn" }
    324 })
    325 
    326 TestGetThrow({
    327   getPropertyDescriptor: function(k) { throw "myexn" }
    328 })
    329 
    330 TestGetThrow({
    331   getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
    332   getPropertyDescriptor2: function(k) { throw "myexn" }
    333 })
    334 
    335 TestGetThrow({
    336   getPropertyDescriptor: function(k) {
    337     return {get value() { throw "myexn" }}
    338   }
    339 })
    340 
    341 TestGetThrow({
    342   get: undefined,
    343   getPropertyDescriptor: function(k) { throw "myexn" }
    344 })
    345 
    346 TestGetThrow(Proxy.create({
    347   get: function(pr, pk) { throw "myexn" }
    348 }))
    349 
    350 TestGetThrow(Proxy.create({
    351   get: function(pr, pk) {
    352     return function(r, k) { throw "myexn" }
    353   }
    354 }))
    355 
    356 
    357 
    358 // Setters.
    359 
    360 var key
    361 var val
    362 
    363 function TestSet(handler) {
    364   TestWithProxies(TestSet2, handler)
    365 }
    366 
    367 function TestSet2(create, handler) {
    368   var p = create(handler)
    369   assertEquals(42, p.a = 42)
    370   assertEquals("a", key)
    371   assertEquals(42, val)
    372   assertEquals(43, p["b"] = 43)
    373   assertEquals("b", key)
    374   assertEquals(43, val)
    375   assertEquals(44, p[77] = 44)
    376   assertEquals("77", key)
    377   assertEquals(44, val)
    378 
    379   assertEquals(45, (function(n) { return p[n] = 45 })("c"))
    380   assertEquals("c", key)
    381   assertEquals(45, val)
    382   assertEquals(46, (function(n) { return p[n] = 46 })(99))
    383   assertEquals("99", key)
    384   assertEquals(46, val)
    385 }
    386 
    387 TestSet({
    388   set: function(r, k, v) { key = k; val = v; return true }
    389 })
    390 
    391 TestSet({
    392   set: function(r, k, v) { return this.set2(r, k, v) },
    393   set2: function(r, k, v) { key = k; val = v; return true }
    394 })
    395 
    396 TestSet({
    397   getOwnPropertyDescriptor: function(k) { return {writable: true} },
    398   defineProperty: function(k, desc) { key = k; val = desc.value }
    399 })
    400 
    401 TestSet({
    402   getOwnPropertyDescriptor: function(k) {
    403     return this.getOwnPropertyDescriptor2(k)
    404   },
    405   getOwnPropertyDescriptor2: function(k) { return {writable: true} },
    406   defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
    407   defineProperty2: function(k, desc) { key = k; val = desc.value }
    408 })
    409 
    410 TestSet({
    411   getOwnPropertyDescriptor: function(k) {
    412     return {get writable() { return true }}
    413   },
    414   defineProperty: function(k, desc) { key = k; val = desc.value }
    415 })
    416 
    417 TestSet({
    418   getOwnPropertyDescriptor: function(k) {
    419     return {set: function(v) { key = k; val = v }}
    420   }
    421 })
    422 
    423 TestSet({
    424   getOwnPropertyDescriptor: function(k) { return null },
    425   getPropertyDescriptor: function(k) { return {writable: true} },
    426   defineProperty: function(k, desc) { key = k; val = desc.value }
    427 })
    428 
    429 TestSet({
    430   getOwnPropertyDescriptor: function(k) { return null },
    431   getPropertyDescriptor: function(k) {
    432     return {get writable() { return true }}
    433   },
    434   defineProperty: function(k, desc) { key = k; val = desc.value }
    435 })
    436 
    437 TestSet({
    438   getOwnPropertyDescriptor: function(k) { return null },
    439   getPropertyDescriptor: function(k) {
    440     return {set: function(v) { key = k; val = v }}
    441   }
    442 })
    443 
    444 TestSet({
    445   getOwnPropertyDescriptor: function(k) { return null },
    446   getPropertyDescriptor: function(k) { return null },
    447   defineProperty: function(k, desc) { key = k, val = desc.value }
    448 })
    449 
    450 TestSet(Proxy.create({
    451   get: function(pr, pk) {
    452     return function(r, k, v) { key = k; val = v; return true }
    453   }
    454 }))
    455 
    456 
    457 function TestSetThrow(handler) {
    458   TestWithProxies(TestSetThrow2, handler)
    459 }
    460 
    461 function TestSetThrow2(create, handler) {
    462   var p = create(handler)
    463   assertThrows(function(){ p.a = 42 }, "myexn")
    464   assertThrows(function(){ p["b"] = 42 }, "myexn")
    465   assertThrows(function(){ p[22] = 42 }, "myexn")
    466   assertThrows(function(){ (function(n) { p[n] = 45 })("c") }, "myexn")
    467   assertThrows(function(){ (function(n) { p[n] = 46 })(99) }, "myexn")
    468 }
    469 
    470 TestSetThrow({
    471   set: function(r, k, v) { throw "myexn" }
    472 })
    473 
    474 TestSetThrow({
    475   set: function(r, k, v) { return this.set2(r, k, v) },
    476   set2: function(r, k, v) { throw "myexn" }
    477 })
    478 
    479 TestSetThrow({
    480   getOwnPropertyDescriptor: function(k) { throw "myexn" },
    481   defineProperty: function(k, desc) { key = k; val = desc.value }
    482 })
    483 
    484 TestSetThrow({
    485   getOwnPropertyDescriptor: function(k) { return {writable: true} },
    486   defineProperty: function(k, desc) { throw "myexn" }
    487 })
    488 
    489 TestSetThrow({
    490   getOwnPropertyDescriptor: function(k) {
    491     return this.getOwnPropertyDescriptor2(k)
    492   },
    493   getOwnPropertyDescriptor2: function(k) { throw "myexn" },
    494   defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
    495   defineProperty2: function(k, desc) { key = k; val = desc.value }
    496 })
    497 
    498 TestSetThrow({
    499   getOwnPropertyDescriptor: function(k) {
    500     return this.getOwnPropertyDescriptor2(k)
    501   },
    502   getOwnPropertyDescriptor2: function(k) { return {writable: true} },
    503   defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
    504   defineProperty2: function(k, desc) { throw "myexn" }
    505 })
    506 
    507 TestSetThrow({
    508   getOwnPropertyDescriptor: function(k) { throw "myexn" },
    509   defineProperty: function(k, desc) { key = k; val = desc.value }
    510 })
    511 
    512 TestSetThrow({
    513   getOwnPropertyDescriptor: function(k) {
    514     return {get writable() { return true }}
    515   },
    516   defineProperty: function(k, desc) { throw "myexn" }
    517 })
    518 
    519 TestSetThrow({
    520   getOwnPropertyDescriptor: function(k) { throw "myexn" }
    521 })
    522 
    523 TestSetThrow({
    524   getOwnPropertyDescriptor: function(k) {
    525     return {set: function(v) { throw "myexn" }}
    526   }
    527 })
    528 
    529 TestSetThrow({
    530   getOwnPropertyDescriptor: function(k) { throw "myexn" },
    531   getPropertyDescriptor: function(k) { return {writable: true} },
    532   defineProperty: function(k, desc) { key = k; val = desc.value }
    533 })
    534 
    535 TestSetThrow({
    536   getOwnPropertyDescriptor: function(k) { return null },
    537   getPropertyDescriptor: function(k) { throw "myexn" },
    538   defineProperty: function(k, desc) { key = k; val = desc.value }
    539 })
    540 
    541 TestSetThrow({
    542   getOwnPropertyDescriptor: function(k) { return null },
    543   getPropertyDescriptor: function(k) { return {writable: true} },
    544   defineProperty: function(k, desc) { throw "myexn" }
    545 })
    546 
    547 TestSetThrow({
    548   getOwnPropertyDescriptor: function(k) { return null },
    549   getPropertyDescriptor: function(k) {
    550     return {get writable() { throw "myexn" }}
    551   },
    552   defineProperty: function(k, desc) { key = k; val = desc.value }
    553 })
    554 
    555 TestSetThrow({
    556   getOwnPropertyDescriptor: function(k) { return null },
    557   getPropertyDescriptor: function(k) {
    558     return {set: function(v) { throw "myexn" }}
    559   }
    560 })
    561 
    562 TestSetThrow({
    563   getOwnPropertyDescriptor: function(k) { return null },
    564   getPropertyDescriptor: function(k) { return null },
    565   defineProperty: function(k, desc) { throw "myexn" }
    566 })
    567 
    568 TestSetThrow(Proxy.create({
    569   get: function(pr, pk) { throw "myexn" }
    570 }))
    571 
    572 TestSetThrow(Proxy.create({
    573   get: function(pr, pk) {
    574     return function(r, k, v) { throw "myexn" }
    575   }
    576 }))
    577 
    578 
    579 var rec
    580 var key
    581 var val
    582 
    583 function TestSetForDerived(trap) {
    584   TestWithProxies(TestSetForDerived2, trap)
    585 }
    586 
    587 function TestSetForDerived2(create, trap) {
    588   var p = create({getPropertyDescriptor: trap, getOwnPropertyDescriptor: trap})
    589   var o = Object.create(p, {x: {value: 88, writable: true},
    590                             '1': {value: 89, writable: true}})
    591 
    592   key = ""
    593   assertEquals(48, o.x = 48)
    594   assertEquals("", key)  // trap not invoked
    595   assertEquals(48, o.x)
    596 
    597   assertEquals(47, o[1] = 47)
    598   assertEquals("", key)  // trap not invoked
    599   assertEquals(47, o[1])
    600 
    601   assertEquals(49, o.y = 49)
    602   assertEquals("y", key)
    603   assertEquals(49, o.y)
    604 
    605   assertEquals(50, o[2] = 50)
    606   assertEquals("2", key)
    607   assertEquals(50, o[2])
    608 
    609   assertEquals(44, o.p_writable = 44)
    610   assertEquals("p_writable", key)
    611   assertEquals(44, o.p_writable)
    612 
    613   assertEquals(45, o.p_nonwritable = 45)
    614   assertEquals("p_nonwritable", key)
    615   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonwritable"))
    616 
    617   assertThrows(function(){ "use strict"; o.p_nonwritable = 45 }, TypeError)
    618   assertEquals("p_nonwritable", key)
    619   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonwritable"))
    620 
    621   val = ""
    622   assertEquals(46, o.p_setter = 46)
    623   assertEquals("p_setter", key)
    624   assertSame(o, rec)
    625   assertEquals(46, val)  // written to parent
    626   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter"))
    627 
    628   val = ""
    629   assertEquals(47, o.p_nosetter = 47)
    630   assertEquals("p_nosetter", key)
    631   assertEquals("", val)  // not written at all
    632   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter"));
    633 
    634   key = ""
    635   assertThrows(function(){ "use strict"; o.p_nosetter = 50 }, TypeError)
    636   assertEquals("p_nosetter", key)
    637   assertEquals("", val)  // not written at all
    638   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nosetter"));
    639 
    640   assertThrows(function(){ o.p_nonconf = 53 }, TypeError)
    641   assertEquals("p_nonconf", key)
    642   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonconf"));
    643 
    644   assertThrows(function(){ o.p_throw = 51 }, "myexn")
    645   assertEquals("p_throw", key)
    646   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_throw"));
    647 
    648   assertThrows(function(){ o.p_setterthrow = 52 }, "myexn")
    649   assertEquals("p_setterthrow", key)
    650   assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setterthrow"));
    651 }
    652 
    653 
    654 TestSetForDerived(
    655   function(k) {
    656     // TODO(yangguo): issue 2398 - throwing an error causes formatting of
    657     // the message string, which can be observable through this handler.
    658     // We ignore keys that occur when formatting the message string.
    659     if (k == "toString" || k == "valueOf") return;
    660 
    661     key = k;
    662     switch (k) {
    663       case "p_writable": return {writable: true, configurable: true}
    664       case "p_nonwritable": return {writable: false, configurable: true}
    665       case "p_setter": return {
    666         set: function(x) { rec = this; val = x },
    667         configurable: true
    668       }
    669       case "p_nosetter": return {
    670         get: function() { return 1 },
    671         configurable: true
    672       }
    673       case "p_nonconf": return {}
    674       case "p_throw": throw "myexn"
    675       case "p_setterthrow": return {set: function(x) { throw "myexn" }}
    676       default: return undefined
    677     }
    678   }
    679 )
    680 
    681 
    682 // Evil proxy-induced side-effects shouldn't crash.
    683 // TODO(rossberg): proper behaviour isn't really spec'ed yet, so ignore results.
    684 
    685 TestWithProxies(function(create) {
    686   var calls = 0
    687   var handler = {
    688     getPropertyDescriptor: function() {
    689       ++calls
    690       return (calls % 2 == 1)
    691         ? {get: function() { return 5 }, configurable: true}
    692         : {set: function() { return false }, configurable: true}
    693     }
    694   }
    695   var p = create(handler)
    696   var o = Object.create(p)
    697   // Make proxy prototype property read-only after CanPut check.
    698   try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
    699 })
    700 
    701 TestWithProxies(function(create) {
    702   var handler = {
    703     getPropertyDescriptor: function() {
    704       Object.defineProperty(o, "x", {get: function() { return 5 }});
    705       return {set: function() {}}
    706     }
    707   }
    708   var p = create(handler)
    709   var o = Object.create(p)
    710   // Make object property read-only after CanPut check.
    711   try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
    712 })
    713 
    714 
    715 
    716 // TODO(rossberg): TestSetReject, returning false
    717 // TODO(rossberg): TestGetProperty, TestSetProperty
    718 
    719 
    720 
    721 // Property definition (Object.defineProperty and Object.defineProperties).
    722 
    723 var key
    724 var desc
    725 
    726 function TestDefine(handler) {
    727   TestWithProxies(TestDefine2, handler)
    728 }
    729 
    730 function TestDefine2(create, handler) {
    731   var p = create(handler)
    732   assertEquals(p, Object.defineProperty(p, "a", {value: 44}))
    733   assertEquals("a", key)
    734   assertEquals(1, Object.getOwnPropertyNames(desc).length)
    735   assertEquals(44, desc.value)
    736 
    737   assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false}))
    738   assertEquals("b", key)
    739   assertEquals(2, Object.getOwnPropertyNames(desc).length)
    740   assertEquals(45, desc.value)
    741   assertEquals(false, desc.writable)
    742 
    743   assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false}))
    744   assertEquals("c", key)
    745   assertEquals(2, Object.getOwnPropertyNames(desc).length)
    746   assertEquals(46, desc.value)
    747   assertEquals(false, desc.enumerable)
    748 
    749   assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false}))
    750   assertEquals("101", key)
    751   assertEquals(2, Object.getOwnPropertyNames(desc).length)
    752   assertEquals(47, desc.value)
    753   assertEquals(false, desc.enumerable)
    754 
    755   var attributes = {configurable: true, mine: 66, minetoo: 23}
    756   assertEquals(p, Object.defineProperty(p, "d", attributes))
    757   assertEquals("d", key)
    758   // Modifying the attributes object after the fact should have no effect.
    759   attributes.configurable = false
    760   attributes.mine = 77
    761   delete attributes.minetoo
    762   assertEquals(3, Object.getOwnPropertyNames(desc).length)
    763   assertEquals(true, desc.configurable)
    764   assertEquals(66, desc.mine)
    765   assertEquals(23, desc.minetoo)
    766 
    767   assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }}))
    768   assertEquals("e", key)
    769   assertEquals(1, Object.getOwnPropertyNames(desc).length)
    770   assertEquals(5, desc.get())
    771 
    772   assertEquals(p, Object.defineProperty(p, "zzz", {}))
    773   assertEquals("zzz", key)
    774   assertEquals(0, Object.getOwnPropertyNames(desc).length)
    775 
    776   var d = create({
    777     get: function(r, k) { return (k === "value") ? 77 : void 0 },
    778     getOwnPropertyNames: function() { return ["value"] },
    779     enumerate: function() { return ["value"] }
    780   })
    781   assertEquals(1, Object.getOwnPropertyNames(d).length)
    782   assertEquals(77, d.value)
    783   assertEquals(p, Object.defineProperty(p, "p", d))
    784   assertEquals("p", key)
    785   assertEquals(1, Object.getOwnPropertyNames(desc).length)
    786   assertEquals(77, desc.value)
    787 
    788   var props = {
    789     '11': {},
    790     blub: {get: function() { return true }},
    791     '': {get value() { return 20 }},
    792     last: {value: 21, configurable: true, mine: "eyes"}
    793   }
    794   Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false})
    795   assertEquals(p, Object.defineProperties(p, props))
    796   assertEquals("last", key)
    797   assertEquals(2, Object.getOwnPropertyNames(desc).length)
    798   assertEquals(21, desc.value)
    799   assertEquals(true, desc.configurable)
    800   assertEquals(undefined, desc.mine)  // Arguably a bug in the spec...
    801 
    802   var props = {bla: {get value() { throw "myexn" }}}
    803   assertThrows(function(){ Object.defineProperties(p, props) }, "myexn")
    804 }
    805 
    806 TestDefine({
    807   defineProperty: function(k, d) { key = k; desc = d; return true }
    808 })
    809 
    810 TestDefine({
    811   defineProperty: function(k, d) { return this.defineProperty2(k, d) },
    812   defineProperty2: function(k, d) { key = k; desc = d; return true }
    813 })
    814 
    815 TestDefine(Proxy.create({
    816   get: function(pr, pk) {
    817     return function(k, d) { key = k; desc = d; return true }
    818   }
    819 }))
    820 
    821 
    822 function TestDefineThrow(handler) {
    823   TestWithProxies(TestDefineThrow2, handler)
    824 }
    825 
    826 function TestDefineThrow2(create, handler) {
    827   var p = create(handler)
    828   assertThrows(function(){ Object.defineProperty(p, "a", {value: 44})}, "myexn")
    829   assertThrows(function(){ Object.defineProperty(p, 0, {value: 44})}, "myexn")
    830 
    831   var d1 = create({
    832     get: function(r, k) { throw "myexn" },
    833     getOwnPropertyNames: function() { return ["value"] }
    834   })
    835   assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn")
    836   var d2 = create({
    837     get: function(r, k) { return 77 },
    838     getOwnPropertyNames: function() { throw "myexn" }
    839   })
    840   assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn")
    841 
    842   var props = {bla: {get value() { throw "otherexn" }}}
    843   assertThrows(function(){ Object.defineProperties(p, props) }, "otherexn")
    844 }
    845 
    846 TestDefineThrow({
    847   defineProperty: function(k, d) { throw "myexn" }
    848 })
    849 
    850 TestDefineThrow({
    851   defineProperty: function(k, d) { return this.defineProperty2(k, d) },
    852   defineProperty2: function(k, d) { throw "myexn" }
    853 })
    854 
    855 TestDefineThrow(Proxy.create({
    856   get: function(pr, pk) { throw "myexn" }
    857 }))
    858 
    859 TestDefineThrow(Proxy.create({
    860   get: function(pr, pk) {
    861     return function(k, d) { throw "myexn" }
    862   }
    863 }))
    864 
    865 
    866 
    867 // Property deletion (delete).
    868 
    869 var key
    870 
    871 function TestDelete(handler) {
    872   TestWithProxies(TestDelete2, handler)
    873 }
    874 
    875 function TestDelete2(create, handler) {
    876   var p = create(handler)
    877   assertEquals(true, delete p.a)
    878   assertEquals("a", key)
    879   assertEquals(true, delete p["b"])
    880   assertEquals("b", key)
    881   assertEquals(true, delete p[1])
    882   assertEquals("1", key)
    883 
    884   assertEquals(false, delete p.z1)
    885   assertEquals("z1", key)
    886   assertEquals(false, delete p["z2"])
    887   assertEquals("z2", key);
    888 
    889   (function() {
    890     "use strict"
    891     assertEquals(true, delete p.c)
    892     assertEquals("c", key)
    893     assertEquals(true, delete p["d"])
    894     assertEquals("d", key)
    895     assertEquals(true, delete p[2])
    896     assertEquals("2", key)
    897 
    898     assertThrows(function(){ delete p.z3 }, TypeError)
    899     assertEquals("z3", key)
    900     assertThrows(function(){ delete p["z4"] }, TypeError)
    901     assertEquals("z4", key)
    902   })()
    903 }
    904 
    905 TestDelete({
    906   delete: function(k) { key = k; return k < "z" }
    907 })
    908 
    909 TestDelete({
    910   delete: function(k) { return this.delete2(k) },
    911   delete2: function(k) { key = k; return k < "z" }
    912 })
    913 
    914 TestDelete(Proxy.create({
    915   get: function(pr, pk) {
    916     return function(k) { key = k; return k < "z" }
    917   }
    918 }))
    919 
    920 
    921 function TestDeleteThrow(handler) {
    922   TestWithProxies(TestDeleteThrow2, handler)
    923 }
    924 
    925 function TestDeleteThrow2(create, handler) {
    926   var p = create(handler)
    927   assertThrows(function(){ delete p.a }, "myexn")
    928   assertThrows(function(){ delete p["b"] }, "myexn");
    929   assertThrows(function(){ delete p[3] }, "myexn");
    930 
    931   (function() {
    932     "use strict"
    933     assertThrows(function(){ delete p.c }, "myexn")
    934     assertThrows(function(){ delete p["d"] }, "myexn")
    935     assertThrows(function(){ delete p[4] }, "myexn");
    936   })()
    937 }
    938 
    939 TestDeleteThrow({
    940   delete: function(k) { throw "myexn" }
    941 })
    942 
    943 TestDeleteThrow({
    944   delete: function(k) { return this.delete2(k) },
    945   delete2: function(k) { throw "myexn" }
    946 })
    947 
    948 TestDeleteThrow(Proxy.create({
    949   get: function(pr, pk) { throw "myexn" }
    950 }))
    951 
    952 TestDeleteThrow(Proxy.create({
    953   get: function(pr, pk) {
    954     return function(k) { throw "myexn" }
    955   }
    956 }))
    957 
    958 
    959 
    960 // Property descriptors (Object.getOwnPropertyDescriptor).
    961 
    962 function TestDescriptor(handler) {
    963   TestWithProxies(TestDescriptor2, handler)
    964 }
    965 
    966 function TestDescriptor2(create, handler) {
    967   var p = create(handler)
    968   var descs = [
    969     {configurable: true},
    970     {value: 34, enumerable: true, configurable: true},
    971     {value: 3, writable: false, mine: "eyes", configurable: true},
    972     {get value() { return 20 }, get configurable() { return true }},
    973     {get: function() { "get" }, set: function() { "set" }, configurable: true}
    974   ]
    975   for (var i = 0; i < descs.length; ++i) {
    976     assertEquals(p, Object.defineProperty(p, i, descs[i]))
    977     var desc = Object.getOwnPropertyDescriptor(p, i)
    978     for (prop in descs[i]) {
    979       // TODO(rossberg): Ignore user attributes as long as the spec isn't
    980       // fixed suitably.
    981       if (prop != "mine") assertEquals(descs[i][prop], desc[prop])
    982     }
    983     assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent"))
    984   }
    985 }
    986 
    987 TestDescriptor({
    988   defineProperty: function(k, d) { this["__" + k] = d; return true },
    989   getOwnPropertyDescriptor: function(k) { return this["__" + k] }
    990 })
    991 
    992 TestDescriptor({
    993   defineProperty: function(k, d) { this["__" + k] = d; return true },
    994   getOwnPropertyDescriptor: function(k) {
    995     return this.getOwnPropertyDescriptor2(k)
    996   },
    997   getOwnPropertyDescriptor2: function(k) { return this["__" + k] }
    998 })
    999 
   1000 
   1001 function TestDescriptorThrow(handler) {
   1002   TestWithProxies(TestDescriptorThrow2, handler)
   1003 }
   1004 
   1005 function TestDescriptorThrow2(create, handler) {
   1006   var p = create(handler)
   1007   assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn")
   1008 }
   1009 
   1010 TestDescriptorThrow({
   1011   getOwnPropertyDescriptor: function(k) { throw "myexn" }
   1012 })
   1013 
   1014 TestDescriptorThrow({
   1015   getOwnPropertyDescriptor: function(k) {
   1016     return this.getOwnPropertyDescriptor2(k)
   1017   },
   1018   getOwnPropertyDescriptor2: function(k) { throw "myexn" }
   1019 })
   1020 
   1021 
   1022 
   1023 // Comparison.
   1024 
   1025 function TestComparison(eq) {
   1026   TestWithProxies(TestComparison2, eq)
   1027 }
   1028 
   1029 function TestComparison2(create, eq) {
   1030   var p1 = create({})
   1031   var p2 = create({})
   1032 
   1033   assertTrue(eq(p1, p1))
   1034   assertTrue(eq(p2, p2))
   1035   assertTrue(!eq(p1, p2))
   1036   assertTrue(!eq(p1, {}))
   1037   assertTrue(!eq({}, p2))
   1038   assertTrue(!eq({}, {}))
   1039 }
   1040 
   1041 TestComparison(function(o1, o2) { return o1 == o2 })
   1042 TestComparison(function(o1, o2) { return o1 === o2 })
   1043 TestComparison(function(o1, o2) { return !(o1 != o2) })
   1044 TestComparison(function(o1, o2) { return !(o1 !== o2) })
   1045 
   1046 
   1047 
   1048 // Type (typeof).
   1049 
   1050 function TestTypeof() {
   1051   assertEquals("object", typeof Proxy.create({}))
   1052   assertTrue(typeof Proxy.create({}) == "object")
   1053   assertTrue("object" == typeof Proxy.create({}))
   1054 
   1055   assertEquals("function", typeof Proxy.createFunction({}, function() {}))
   1056   assertTrue(typeof Proxy.createFunction({}, function() {}) == "function")
   1057   assertTrue("function" == typeof Proxy.createFunction({}, function() {}))
   1058 }
   1059 
   1060 TestTypeof()
   1061 
   1062 
   1063 
   1064 // Membership test (in).
   1065 
   1066 var key
   1067 
   1068 function TestIn(handler) {
   1069   TestWithProxies(TestIn2, handler)
   1070 }
   1071 
   1072 function TestIn2(create, handler) {
   1073   var p = create(handler)
   1074   assertTrue("a" in p)
   1075   assertEquals("a", key)
   1076   assertTrue(99 in p)
   1077   assertEquals("99", key)
   1078   assertFalse("z" in p)
   1079   assertEquals("z", key)
   1080 
   1081   assertEquals(2, ("a" in p) ? 2 : 0)
   1082   assertEquals(0, !("a" in p) ? 2 : 0)
   1083   assertEquals(0, ("zzz" in p) ? 2 : 0)
   1084   assertEquals(2, !("zzz" in p) ? 2 : 0)
   1085 
   1086   // Test compilation in conditionals.
   1087   if ("b" in p) {
   1088   } else {
   1089     assertTrue(false)
   1090   }
   1091   assertEquals("b", key)
   1092 
   1093   if ("zz" in p) {
   1094     assertTrue(false)
   1095   }
   1096   assertEquals("zz", key)
   1097 
   1098   if (!("c" in p)) {
   1099     assertTrue(false)
   1100   }
   1101   assertEquals("c", key)
   1102 
   1103   if (!("zzz" in p)) {
   1104   } else {
   1105     assertTrue(false)
   1106   }
   1107   assertEquals("zzz", key)
   1108 }
   1109 
   1110 TestIn({
   1111   has: function(k) { key = k; return k < "z" }
   1112 })
   1113 
   1114 TestIn({
   1115   has: function(k) { return this.has2(k) },
   1116   has2: function(k) { key = k; return k < "z" }
   1117 })
   1118 
   1119 TestIn({
   1120   getPropertyDescriptor: function(k) {
   1121     key = k; return k < "z" ? {value: 42} : void 0
   1122   }
   1123 })
   1124 
   1125 TestIn({
   1126   getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
   1127   getPropertyDescriptor2: function(k) {
   1128     key = k; return k < "z" ? {value: 42} : void 0
   1129   }
   1130 })
   1131 
   1132 TestIn({
   1133   getPropertyDescriptor: function(k) {
   1134     key = k; return k < "z" ? {get value() { return 42 }} : void 0
   1135   }
   1136 })
   1137 
   1138 TestIn({
   1139   has: undefined,
   1140   getPropertyDescriptor: function(k) {
   1141     key = k; return k < "z" ? {value: 42} : void 0
   1142   }
   1143 })
   1144 
   1145 TestIn(Proxy.create({
   1146   get: function(pr, pk) {
   1147     return function(k) { key = k; return k < "z" }
   1148   }
   1149 }))
   1150 
   1151 
   1152 function TestInThrow(handler) {
   1153   TestWithProxies(TestInThrow2, handler)
   1154 }
   1155 
   1156 function TestInThrow2(create, handler) {
   1157   var p = create(handler)
   1158   assertThrows(function(){ return "a" in o }, "myexn")
   1159   assertThrows(function(){ return 99 in o }, "myexn")
   1160   assertThrows(function(){ return !("a" in o) }, "myexn")
   1161   assertThrows(function(){ return ("a" in o) ? 2 : 3 }, "myexn")
   1162   assertThrows(function(){ if ("b" in o) {} }, "myexn")
   1163   assertThrows(function(){ if (!("b" in o)) {} }, "myexn")
   1164   assertThrows(function(){ if ("zzz" in o) {} }, "myexn")
   1165 }
   1166 
   1167 TestInThrow({
   1168   has: function(k) { throw "myexn" }
   1169 })
   1170 
   1171 TestInThrow({
   1172   has: function(k) { return this.has2(k) },
   1173   has2: function(k) { throw "myexn" }
   1174 })
   1175 
   1176 TestInThrow({
   1177   getPropertyDescriptor: function(k) { throw "myexn" }
   1178 })
   1179 
   1180 TestInThrow({
   1181   getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
   1182   getPropertyDescriptor2: function(k) { throw "myexn" }
   1183 })
   1184 
   1185 TestInThrow({
   1186   has: undefined,
   1187   getPropertyDescriptor: function(k) { throw "myexn" }
   1188 })
   1189 
   1190 TestInThrow(Proxy.create({
   1191   get: function(pr, pk) { throw "myexn" }
   1192 }))
   1193 
   1194 TestInThrow(Proxy.create({
   1195   get: function(pr, pk) {
   1196     return function(k) { throw "myexn" }
   1197   }
   1198 }))
   1199 
   1200 
   1201 function TestInForDerived(handler) {
   1202   TestWithProxies(TestInForDerived2, handler)
   1203 }
   1204 
   1205 function TestInForDerived2(create, handler) {
   1206   var p = create(handler)
   1207   var o = Object.create(p)
   1208 
   1209   assertTrue("a" in o)
   1210   assertEquals("a", key)
   1211   assertTrue(99 in o)
   1212   assertEquals("99", key)
   1213   assertFalse("z" in o)
   1214   assertEquals("z", key)
   1215 
   1216   assertEquals(2, ("a" in o) ? 2 : 0)
   1217   assertEquals(0, !("a" in o) ? 2 : 0)
   1218   assertEquals(0, ("zzz" in o) ? 2 : 0)
   1219   assertEquals(2, !("zzz" in o) ? 2 : 0)
   1220 
   1221   if ("b" in o) {
   1222   } else {
   1223     assertTrue(false)
   1224   }
   1225   assertEquals("b", key)
   1226 
   1227   if ("zz" in o) {
   1228     assertTrue(false)
   1229   }
   1230   assertEquals("zz", key)
   1231 
   1232   if (!("c" in o)) {
   1233     assertTrue(false)
   1234   }
   1235   assertEquals("c", key)
   1236 
   1237   if (!("zzz" in o)) {
   1238   } else {
   1239     assertTrue(false)
   1240   }
   1241   assertEquals("zzz", key)
   1242 }
   1243 
   1244 TestInForDerived({
   1245   getPropertyDescriptor: function(k) {
   1246     key = k; return k < "z" ? {value: 42, configurable: true} : void 0
   1247   }
   1248 })
   1249 
   1250 TestInForDerived({
   1251   getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
   1252   getPropertyDescriptor2: function(k) {
   1253     key = k; return k < "z" ? {value: 42, configurable: true} : void 0
   1254   }
   1255 })
   1256 
   1257 TestInForDerived({
   1258   getPropertyDescriptor: function(k) {
   1259     key = k;
   1260     return k < "z" ? {get value() { return 42 }, configurable: true} : void 0
   1261   }
   1262 })
   1263 
   1264 /* TODO(rossberg): this will work once we implement the newest proposal
   1265  * regarding default traps for getPropertyDescriptor.
   1266 TestInForDerived({
   1267   getOwnPropertyDescriptor: function(k) {
   1268     key = k; return k < "z" ? {value: 42, configurable: true} : void 0
   1269   }
   1270 })
   1271 
   1272 TestInForDerived({
   1273   getOwnPropertyDescriptor: function(k) {
   1274     return this.getOwnPropertyDescriptor2(k)
   1275   },
   1276   getOwnPropertyDescriptor2: function(k) {
   1277     key = k; return k < "z" ? {value: 42, configurable: true} : void 0
   1278   }
   1279 })
   1280 
   1281 TestInForDerived({
   1282   getOwnPropertyDescriptor: function(k) {
   1283     key = k;
   1284     return k < "z" ? {get value() { return 42 }, configurable: true} : void 0
   1285   }
   1286 })
   1287 */
   1288 
   1289 TestInForDerived(Proxy.create({
   1290   get: function(pr, pk) {
   1291     return function(k) {
   1292       key = k; return k < "z" ? {value: 42, configurable: true} : void 0
   1293     }
   1294   }
   1295 }))
   1296 
   1297 
   1298 
   1299 // Property descriptor conversion.
   1300 
   1301 var descget
   1302 
   1303 function TestDescriptorGetOrder(handler) {
   1304   var p = Proxy.create(handler)
   1305   var o = Object.create(p, {b: {value: 0}})
   1306   TestDescriptorGetOrder2(function(n) { return p[n] }, "vV")
   1307   TestDescriptorGetOrder2(function(n) { return n in p }, "")
   1308   TestDescriptorGetOrder2(function(n) { return o[n] }, "vV")
   1309   TestDescriptorGetOrder2(function(n) { return n in o }, "eEcCvVwWgs")
   1310 }
   1311 
   1312 function TestDescriptorGetOrder2(f, access) {
   1313   descget = ""
   1314   assertTrue(f("a"))
   1315   assertEquals(access, descget)
   1316   descget = ""
   1317   assertTrue(f(99))
   1318   assertEquals(access, descget)
   1319   descget = ""
   1320   assertFalse(!!f("z"))
   1321   assertEquals("", descget)
   1322 }
   1323 
   1324 TestDescriptorGetOrder({
   1325   getPropertyDescriptor: function(k) {
   1326     if (k >= "z") return void 0
   1327     // Return a proxy as property descriptor, so that we can log accesses.
   1328     return Proxy.create({
   1329       get: function(r, attr) {
   1330         descget += attr[0].toUpperCase()
   1331         return true
   1332       },
   1333       has: function(attr) {
   1334         descget += attr[0]
   1335         switch (attr) {
   1336           case "writable":
   1337           case "enumerable":
   1338           case "configurable":
   1339           case "value":
   1340             return true
   1341           case "get":
   1342           case "set":
   1343             return false
   1344           default:
   1345             assertUnreachable()
   1346         }
   1347       }
   1348     })
   1349   }
   1350 })
   1351 
   1352 
   1353 
   1354 // Own Properties (Object.prototype.hasOwnProperty).
   1355 
   1356 var key
   1357 
   1358 function TestHasOwn(handler) {
   1359   TestWithProxies(TestHasOwn2, handler)
   1360 }
   1361 
   1362 function TestHasOwn2(create, handler) {
   1363   var p = create(handler)
   1364   assertTrue(Object.prototype.hasOwnProperty.call(p, "a"))
   1365   assertEquals("a", key)
   1366   assertTrue(Object.prototype.hasOwnProperty.call(p, 99))
   1367   assertEquals("99", key)
   1368   assertFalse(Object.prototype.hasOwnProperty.call(p, "z"))
   1369   assertEquals("z", key)
   1370 }
   1371 
   1372 TestHasOwn({
   1373   hasOwn: function(k) { key = k; return k < "z" }
   1374 })
   1375 
   1376 TestHasOwn({
   1377   hasOwn: function(k) { return this.hasOwn2(k) },
   1378   hasOwn2: function(k) { key = k; return k < "z" }
   1379 })
   1380 
   1381 TestHasOwn({
   1382   getOwnPropertyDescriptor: function(k) {
   1383     key = k; return k < "z" ? {value: 42} : void 0
   1384   }
   1385 })
   1386 
   1387 TestHasOwn({
   1388   getOwnPropertyDescriptor: function(k) {
   1389     return this.getOwnPropertyDescriptor2(k)
   1390   },
   1391   getOwnPropertyDescriptor2: function(k) {
   1392     key = k; return k < "z" ? {value: 42} : void 0
   1393   }
   1394 })
   1395 
   1396 TestHasOwn({
   1397   getOwnPropertyDescriptor: function(k) {
   1398     key = k; return k < "z" ? {get value() { return 42 }} : void 0
   1399   }
   1400 })
   1401 
   1402 TestHasOwn({
   1403   hasOwn: undefined,
   1404   getOwnPropertyDescriptor: function(k) {
   1405     key = k; return k < "z" ? {value: 42} : void 0
   1406   }
   1407 })
   1408 
   1409 TestHasOwn(Proxy.create({
   1410   get: function(pr, pk) {
   1411     return function(k) { key = k; return k < "z" }
   1412   }
   1413 }))
   1414 
   1415 
   1416 function TestHasOwnThrow(handler) {
   1417   TestWithProxies(TestHasOwnThrow2, handler)
   1418 }
   1419 
   1420 function TestHasOwnThrow2(create, handler) {
   1421   var p = create(handler)
   1422   assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, "a")},
   1423     "myexn")
   1424   assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, 99)},
   1425     "myexn")
   1426 }
   1427 
   1428 TestHasOwnThrow({
   1429   hasOwn: function(k) { throw "myexn" }
   1430 })
   1431 
   1432 TestHasOwnThrow({
   1433   hasOwn: function(k) { return this.hasOwn2(k) },
   1434   hasOwn2: function(k) { throw "myexn" }
   1435 })
   1436 
   1437 TestHasOwnThrow({
   1438   getOwnPropertyDescriptor: function(k) { throw "myexn" }
   1439 })
   1440 
   1441 TestHasOwnThrow({
   1442   getOwnPropertyDescriptor: function(k) {
   1443     return this.getOwnPropertyDescriptor2(k)
   1444   },
   1445   getOwnPropertyDescriptor2: function(k) { throw "myexn" }
   1446 })
   1447 
   1448 TestHasOwnThrow({
   1449   hasOwn: undefined,
   1450   getOwnPropertyDescriptor: function(k) { throw "myexn" }
   1451 })
   1452 
   1453 TestHasOwnThrow(Proxy.create({
   1454   get: function(pr, pk) { throw "myexn" }
   1455 }))
   1456 
   1457 TestHasOwnThrow(Proxy.create({
   1458   get: function(pr, pk) {
   1459     return function(k) { throw "myexn" }
   1460   }
   1461 }))
   1462 
   1463 
   1464 
   1465 // Instanceof (instanceof)
   1466 
   1467 function TestProxyInstanceof() {
   1468   var o1 = {}
   1469   var p1 = Proxy.create({})
   1470   var p2 = Proxy.create({}, o1)
   1471   var p3 = Proxy.create({}, p2)
   1472   var o2 = Object.create(p2)
   1473 
   1474   var f0 = function() {}
   1475   f0.prototype = o1
   1476   var f1 = function() {}
   1477   f1.prototype = p1
   1478   var f2 = function() {}
   1479   f2.prototype = p2
   1480   var f3 = function() {}
   1481   f3.prototype = o2
   1482 
   1483   assertTrue(o1 instanceof Object)
   1484   assertFalse(o1 instanceof f0)
   1485   assertFalse(o1 instanceof f1)
   1486   assertFalse(o1 instanceof f2)
   1487   assertFalse(o1 instanceof f3)
   1488   assertFalse(p1 instanceof Object)
   1489   assertFalse(p1 instanceof f0)
   1490   assertFalse(p1 instanceof f1)
   1491   assertFalse(p1 instanceof f2)
   1492   assertFalse(p1 instanceof f3)
   1493   assertTrue(p2 instanceof Object)
   1494   assertTrue(p2 instanceof f0)
   1495   assertFalse(p2 instanceof f1)
   1496   assertFalse(p2 instanceof f2)
   1497   assertFalse(p2 instanceof f3)
   1498   assertTrue(p3 instanceof Object)
   1499   assertTrue(p3 instanceof f0)
   1500   assertFalse(p3 instanceof f1)
   1501   assertTrue(p3 instanceof f2)
   1502   assertFalse(p3 instanceof f3)
   1503   assertTrue(o2 instanceof Object)
   1504   assertTrue(o2 instanceof f0)
   1505   assertFalse(o2 instanceof f1)
   1506   assertTrue(o2 instanceof f2)
   1507   assertFalse(o2 instanceof f3)
   1508 
   1509   var f = Proxy.createFunction({}, function() {})
   1510   assertTrue(f instanceof Function)
   1511 }
   1512 
   1513 TestProxyInstanceof()
   1514 
   1515 
   1516 function TestInstanceofProxy() {
   1517   var o0 = Object.create(null)
   1518   var o1 = {}
   1519   var o2 = Object.create(o0)
   1520   var o3 = Object.create(o1)
   1521   var o4 = Object.create(o2)
   1522   var o5 = Object.create(o3)
   1523 
   1524   function handler(o) { return {get: function() { return o } } }
   1525   var f0 = Proxy.createFunction(handler(o0), function() {})
   1526   var f1 = Proxy.createFunction(handler(o1), function() {})
   1527   var f2 = Proxy.createFunction(handler(o2), function() {})
   1528   var f3 = Proxy.createFunction(handler(o3), function() {})
   1529   var f4 = Proxy.createFunction(handler(o4), function() {})
   1530   var f5 = Proxy.createFunction(handler(o4), function() {})
   1531 
   1532   assertFalse(null instanceof f0)
   1533   assertFalse(o0 instanceof f0)
   1534   assertFalse(o0 instanceof f1)
   1535   assertFalse(o0 instanceof f2)
   1536   assertFalse(o0 instanceof f3)
   1537   assertFalse(o0 instanceof f4)
   1538   assertFalse(o0 instanceof f5)
   1539   assertFalse(o1 instanceof f0)
   1540   assertFalse(o1 instanceof f1)
   1541   assertFalse(o1 instanceof f2)
   1542   assertFalse(o1 instanceof f3)
   1543   assertFalse(o1 instanceof f4)
   1544   assertFalse(o1 instanceof f5)
   1545   assertTrue(o2 instanceof f0)
   1546   assertFalse(o2 instanceof f1)
   1547   assertFalse(o2 instanceof f2)
   1548   assertFalse(o2 instanceof f3)
   1549   assertFalse(o2 instanceof f4)
   1550   assertFalse(o2 instanceof f5)
   1551   assertFalse(o3 instanceof f0)
   1552   assertTrue(o3 instanceof f1)
   1553   assertFalse(o3 instanceof f2)
   1554   assertFalse(o3 instanceof f3)
   1555   assertFalse(o3 instanceof f4)
   1556   assertFalse(o3 instanceof f5)
   1557   assertTrue(o4 instanceof f0)
   1558   assertFalse(o4 instanceof f1)
   1559   assertTrue(o4 instanceof f2)
   1560   assertFalse(o4 instanceof f3)
   1561   assertFalse(o4 instanceof f4)
   1562   assertFalse(o4 instanceof f5)
   1563   assertFalse(o5 instanceof f0)
   1564   assertTrue(o5 instanceof f1)
   1565   assertFalse(o5 instanceof f2)
   1566   assertTrue(o5 instanceof f3)
   1567   assertFalse(o5 instanceof f4)
   1568   assertFalse(o5 instanceof f5)
   1569 
   1570   var f = Proxy.createFunction({}, function() {})
   1571   var ff = Proxy.createFunction(handler(Function), function() {})
   1572   assertTrue(f instanceof Function)
   1573   assertFalse(f instanceof ff)
   1574 }
   1575 
   1576 TestInstanceofProxy()
   1577 
   1578 
   1579 
   1580 // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
   1581 
   1582 function TestPrototype() {
   1583   var o1 = {}
   1584   var p1 = Proxy.create({})
   1585   var p2 = Proxy.create({}, o1)
   1586   var p3 = Proxy.create({}, p2)
   1587   var p4 = Proxy.create({}, null)
   1588   var o2 = Object.create(p3)
   1589 
   1590   assertSame(Object.getPrototypeOf(o1), Object.prototype)
   1591   assertSame(Object.getPrototypeOf(p1), null)
   1592   assertSame(Object.getPrototypeOf(p2), o1)
   1593   assertSame(Object.getPrototypeOf(p3), p2)
   1594   assertSame(Object.getPrototypeOf(p4), null)
   1595   assertSame(Object.getPrototypeOf(o2), p3)
   1596 
   1597   assertTrue(Object.prototype.isPrototypeOf(o1))
   1598   assertFalse(Object.prototype.isPrototypeOf(p1))
   1599   assertTrue(Object.prototype.isPrototypeOf(p2))
   1600   assertTrue(Object.prototype.isPrototypeOf(p3))
   1601   assertFalse(Object.prototype.isPrototypeOf(p4))
   1602   assertTrue(Object.prototype.isPrototypeOf(o2))
   1603   assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1))
   1604   assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1))
   1605   assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2))
   1606   assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3))
   1607   assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4))
   1608   assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2))
   1609   assertFalse(Object.prototype.isPrototypeOf.call(o1, o1))
   1610   assertFalse(Object.prototype.isPrototypeOf.call(o1, p1))
   1611   assertTrue(Object.prototype.isPrototypeOf.call(o1, p2))
   1612   assertTrue(Object.prototype.isPrototypeOf.call(o1, p3))
   1613   assertFalse(Object.prototype.isPrototypeOf.call(o1, p4))
   1614   assertTrue(Object.prototype.isPrototypeOf.call(o1, o2))
   1615   assertFalse(Object.prototype.isPrototypeOf.call(p1, p1))
   1616   assertFalse(Object.prototype.isPrototypeOf.call(p1, o1))
   1617   assertFalse(Object.prototype.isPrototypeOf.call(p1, p2))
   1618   assertFalse(Object.prototype.isPrototypeOf.call(p1, p3))
   1619   assertFalse(Object.prototype.isPrototypeOf.call(p1, p4))
   1620   assertFalse(Object.prototype.isPrototypeOf.call(p1, o2))
   1621   assertFalse(Object.prototype.isPrototypeOf.call(p2, p1))
   1622   assertFalse(Object.prototype.isPrototypeOf.call(p2, p2))
   1623   assertTrue(Object.prototype.isPrototypeOf.call(p2, p3))
   1624   assertFalse(Object.prototype.isPrototypeOf.call(p2, p4))
   1625   assertTrue(Object.prototype.isPrototypeOf.call(p2, o2))
   1626   assertFalse(Object.prototype.isPrototypeOf.call(p3, p2))
   1627   assertTrue(Object.prototype.isPrototypeOf.call(p3, o2))
   1628   assertFalse(Object.prototype.isPrototypeOf.call(o2, o1))
   1629   assertFalse(Object.prototype.isPrototypeOf.call(o2, p1))
   1630   assertFalse(Object.prototype.isPrototypeOf.call(o2, p2))
   1631   assertFalse(Object.prototype.isPrototypeOf.call(o2, p3))
   1632   assertFalse(Object.prototype.isPrototypeOf.call(o2, p4))
   1633   assertFalse(Object.prototype.isPrototypeOf.call(o2, o2))
   1634 
   1635   var f = Proxy.createFunction({}, function() {})
   1636   assertSame(Object.getPrototypeOf(f), Function.prototype)
   1637   assertTrue(Object.prototype.isPrototypeOf(f))
   1638   assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f))
   1639 }
   1640 
   1641 TestPrototype()
   1642 
   1643 
   1644 
   1645 // Property names (Object.getOwnPropertyNames, Object.keys).
   1646 
   1647 function TestPropertyNames(names, handler) {
   1648   TestWithProxies(TestPropertyNames2, handler, names)
   1649 }
   1650 
   1651 function TestPropertyNames2(create, handler, names) {
   1652   var p = create(handler)
   1653   assertArrayEquals(names, Object.getOwnPropertyNames(p))
   1654 }
   1655 
   1656 TestPropertyNames([], {
   1657   getOwnPropertyNames: function() { return [] }
   1658 })
   1659 
   1660 TestPropertyNames(["a", "zz", " ", "0", "toString"], {
   1661   getOwnPropertyNames: function() { return ["a", "zz", " ", 0, "toString"] }
   1662 })
   1663 
   1664 TestPropertyNames(["throw", "function "], {
   1665   getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
   1666   getOwnPropertyNames2: function() { return ["throw", "function "] }
   1667 })
   1668 
   1669 TestPropertyNames(["[object Object]"], {
   1670   get getOwnPropertyNames() {
   1671     return function() { return [{}] }
   1672   }
   1673 })
   1674 
   1675 
   1676 function TestPropertyNamesThrow(handler) {
   1677   TestWithProxies(TestPropertyNamesThrow2, handler)
   1678 }
   1679 
   1680 function TestPropertyNamesThrow2(create, handler) {
   1681   var p = create(handler)
   1682   assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn")
   1683 }
   1684 
   1685 TestPropertyNamesThrow({
   1686   getOwnPropertyNames: function() { throw "myexn" }
   1687 })
   1688 
   1689 TestPropertyNamesThrow({
   1690   getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
   1691   getOwnPropertyNames2: function() { throw "myexn" }
   1692 })
   1693 
   1694 
   1695 function TestKeys(names, handler) {
   1696   TestWithProxies(TestKeys2, handler, names)
   1697 }
   1698 
   1699 function TestKeys2(create, handler, names) {
   1700   var p = create(handler)
   1701   assertArrayEquals(names, Object.keys(p))
   1702 }
   1703 
   1704 TestKeys([], {
   1705   keys: function() { return [] }
   1706 })
   1707 
   1708 TestKeys(["a", "zz", " ", "0", "toString"], {
   1709   keys: function() { return ["a", "zz", " ", 0, "toString"] }
   1710 })
   1711 
   1712 TestKeys(["throw", "function "], {
   1713   keys: function() { return this.keys2() },
   1714   keys2: function() { return ["throw", "function "] }
   1715 })
   1716 
   1717 TestKeys(["[object Object]"], {
   1718   get keys() {
   1719     return function() { return [{}] }
   1720   }
   1721 })
   1722 
   1723 TestKeys(["a", "0"], {
   1724   getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] },
   1725   getOwnPropertyDescriptor: function(k) {
   1726     return k == "" ? undefined : {enumerable: k.length == 1}
   1727   }
   1728 })
   1729 
   1730 TestKeys(["23", "zz", ""], {
   1731   getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
   1732   getOwnPropertyNames2: function() { return ["a", 23, "zz", "", 0] },
   1733   getOwnPropertyDescriptor: function(k) {
   1734     return this.getOwnPropertyDescriptor2(k)
   1735   },
   1736   getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} }
   1737 })
   1738 
   1739 TestKeys(["a", "b", "c", "5"], {
   1740   get getOwnPropertyNames() {
   1741     return function() { return ["0", 4, "a", "b", "c", 5, "ety"] }
   1742   },
   1743   get getOwnPropertyDescriptor() {
   1744     return function(k) {
   1745       return k == "ety" ? undefined : {enumerable: k >= "44"}
   1746     }
   1747   }
   1748 })
   1749 
   1750 TestKeys([], {
   1751   get getOwnPropertyNames() {
   1752     return function() { return ["a", "b", "c"] }
   1753   },
   1754   getOwnPropertyDescriptor: function(k) { return {} }
   1755 })
   1756 
   1757 
   1758 function TestKeysThrow(handler) {
   1759   TestWithProxies(TestKeysThrow2, handler)
   1760 }
   1761 
   1762 function TestKeysThrow2(create, handler) {
   1763   var p = create(handler)
   1764   assertThrows(function(){ Object.keys(p) }, "myexn")
   1765 }
   1766 
   1767 TestKeysThrow({
   1768   keys: function() { throw "myexn" }
   1769 })
   1770 
   1771 TestKeysThrow({
   1772   keys: function() { return this.keys2() },
   1773   keys2: function() { throw "myexn" }
   1774 })
   1775 
   1776 TestKeysThrow({
   1777   getOwnPropertyNames: function() { throw "myexn" },
   1778   getOwnPropertyDescriptor: function(k) { return true }
   1779 })
   1780 
   1781 TestKeysThrow({
   1782   getOwnPropertyNames: function() { return [1, 2] },
   1783   getOwnPropertyDescriptor: function(k) { throw "myexn" }
   1784 })
   1785 
   1786 TestKeysThrow({
   1787   getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
   1788   getOwnPropertyNames2: function() { throw "myexn" },
   1789 })
   1790 
   1791 TestKeysThrow({
   1792   getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
   1793   getOwnPropertyNames2: function() { return [1, 2] },
   1794   getOwnPropertyDescriptor: function(k) {
   1795     return this.getOwnPropertyDescriptor2(k)
   1796   },
   1797   getOwnPropertyDescriptor2: function(k) { throw "myexn" }
   1798 })
   1799 
   1800 TestKeysThrow({
   1801   get getOwnPropertyNames() { throw "myexn" }
   1802 })
   1803 
   1804 TestKeysThrow({
   1805   get getOwnPropertyNames() {
   1806     return function() { throw "myexn" }
   1807   },
   1808 })
   1809 
   1810 TestKeysThrow({
   1811   get getOwnPropertyNames() {
   1812     return function() { return [1, 2] }
   1813   },
   1814   getOwnPropertyDescriptor: function(k) { throw "myexn" }
   1815 })
   1816 
   1817 
   1818 
   1819 // Fixing (Object.freeze, Object.seal, Object.preventExtensions,
   1820 //         Object.isFrozen, Object.isSealed, Object.isExtensible)
   1821 
   1822 function TestFix(names, handler) {
   1823   var proto = {p: 77}
   1824   var assertFixing = function(o, s, f, e) {
   1825     assertEquals(s, Object.isSealed(o))
   1826     assertEquals(f, Object.isFrozen(o))
   1827     assertEquals(e, Object.isExtensible(o))
   1828   }
   1829 
   1830   var p1 = Proxy.create(handler, proto)
   1831   assertFixing(p1, false, false, true)
   1832   Object.seal(p1)
   1833   assertFixing(p1, true, names.length === 0, false)
   1834   assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p1).sort())
   1835   assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
   1836                     Object.keys(p1).sort())
   1837   assertEquals(proto, Object.getPrototypeOf(p1))
   1838   assertEquals(77, p1.p)
   1839   for (var n in p1) {
   1840     var desc = Object.getOwnPropertyDescriptor(p1, n)
   1841     if (desc !== undefined) assertFalse(desc.configurable)
   1842   }
   1843 
   1844   var p2 = Proxy.create(handler, proto)
   1845   assertFixing(p2, false, false, true)
   1846   Object.freeze(p2)
   1847   assertFixing(p2, true, true, false)
   1848   assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p2).sort())
   1849   assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
   1850                     Object.keys(p2).sort())
   1851   assertEquals(proto, Object.getPrototypeOf(p2))
   1852   assertEquals(77, p2.p)
   1853   for (var n in p2) {
   1854     var desc = Object.getOwnPropertyDescriptor(p2, n)
   1855     if (desc !== undefined) assertFalse(desc.writable)
   1856     if (desc !== undefined) assertFalse(desc.configurable)
   1857   }
   1858 
   1859   var p3 = Proxy.create(handler, proto)
   1860   assertFixing(p3, false, false, true)
   1861   Object.preventExtensions(p3)
   1862   assertFixing(p3, names.length === 0, names.length === 0, false)
   1863   assertArrayEquals(names.sort(), Object.getOwnPropertyNames(p3).sort())
   1864   assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
   1865                     Object.keys(p3).sort())
   1866   assertEquals(proto, Object.getPrototypeOf(p3))
   1867   assertEquals(77, p3.p)
   1868 
   1869   var p = Proxy.create(handler, proto)
   1870   var o = Object.create(p)
   1871   assertFixing(p, false, false, true)
   1872   assertFixing(o, false, false, true)
   1873   Object.freeze(o)
   1874   assertFixing(p, false, false, true)
   1875   assertFixing(o, true, true, false)
   1876 }
   1877 
   1878 TestFix([], {
   1879   fix: function() { return {} }
   1880 })
   1881 
   1882 TestFix(["a", "b", "c", "3", "zz"], {
   1883   fix: function() {
   1884     return {
   1885       a: {value: "a", writable: true, configurable: false, enumerable: true},
   1886       b: {value: 33, writable: false, configurable: false, enumerable: true},
   1887       c: {value: 0, writable: true, configurable: true, enumerable: true},
   1888       '3': {value: true, writable: false, configurable: true, enumerable: true},
   1889       zz: {value: 0, enumerable: false}
   1890     }
   1891   }
   1892 })
   1893 
   1894 TestFix(["a"], {
   1895   fix: function() { return this.fix2() },
   1896   fix2: function() {
   1897     return {a: {value: 4, writable: true, configurable: true, enumerable: true}}
   1898   }
   1899 })
   1900 
   1901 TestFix(["b"], {
   1902   get fix() {
   1903     return function() {
   1904       return {b: {configurable: true, writable: true, enumerable: true}}
   1905     }
   1906   }
   1907 })
   1908 
   1909 
   1910 function TestFixFunction(fix) {
   1911   var f1 = Proxy.createFunction({
   1912     fix: function() { return {} }
   1913   }, function() {})
   1914   fix(f1)
   1915   assertEquals(0, f1.length)
   1916 
   1917   var f2 = Proxy.createFunction({
   1918     fix: function() { return {length: {value: 3}} }
   1919   }, function() {})
   1920   fix(f2)
   1921   assertEquals(3, f2.length)
   1922 
   1923   var f3 = Proxy.createFunction({
   1924     fix: function() { return {length: {value: "huh"}} }
   1925   }, function() {})
   1926   fix(f3)
   1927   assertEquals(0, f1.length)
   1928 }
   1929 
   1930 TestFixFunction(Object.seal)
   1931 TestFixFunction(Object.freeze)
   1932 TestFixFunction(Object.preventExtensions)
   1933 
   1934 
   1935 function TestFixThrow(handler) {
   1936   TestWithProxies(TestFixThrow2, handler)
   1937 }
   1938 
   1939 function TestFixThrow2(create, handler) {
   1940   var p = create(handler, {})
   1941   assertThrows(function(){ Object.seal(p) }, "myexn")
   1942   assertThrows(function(){ Object.freeze(p) }, "myexn")
   1943   assertThrows(function(){ Object.preventExtensions(p) }, "myexn")
   1944 }
   1945 
   1946 TestFixThrow({
   1947   fix: function() { throw "myexn" }
   1948 })
   1949 
   1950 TestFixThrow({
   1951   fix: function() { return this.fix2() },
   1952   fix2: function() { throw "myexn" }
   1953 })
   1954 
   1955 TestFixThrow({
   1956   get fix() { throw "myexn" }
   1957 })
   1958 
   1959 TestFixThrow({
   1960   get fix() {
   1961     return function() { throw "myexn" }
   1962   }
   1963 })
   1964 
   1965 
   1966 // Freeze a proxy in the middle of operations on it.
   1967 // TODO(rossberg): actual behaviour not specified consistently at the moment,
   1968 // just make sure that we do not crash.
   1969 function TestReentrantFix(f) {
   1970   TestWithProxies(f, Object.freeze)
   1971   TestWithProxies(f, Object.seal)
   1972   TestWithProxies(f, Object.preventExtensions)
   1973 }
   1974 
   1975 TestReentrantFix(function(create, freeze) {
   1976   var handler = {
   1977     get get() { freeze(p); return undefined },
   1978     fix: function() { return {} }
   1979   }
   1980   var p = create(handler)
   1981   // Freeze while getting get trap.
   1982   try { p.x } catch (e) { assertInstanceof(e, Error) }
   1983 })
   1984 
   1985 TestReentrantFix(function(create, freeze) {
   1986   var handler = {
   1987     get: function() { freeze(p); return 3 },
   1988     fix: function() { return {} }
   1989   }
   1990   var p = create(handler)
   1991   // Freeze while executing get trap.
   1992   try { p.x } catch (e) { assertInstanceof(e, Error) }
   1993 })
   1994 
   1995 TestReentrantFix(function(create, freeze) {
   1996   var handler = {
   1997     getPropertyDescriptor: function() { freeze(p); return undefined },
   1998     fix: function() { return {} }
   1999   }
   2000   var p = create(handler)
   2001   // Freeze while executing default get trap.
   2002   try { p.x } catch (e) { assertInstanceof(e, Error) }
   2003 })
   2004 
   2005 TestReentrantFix(function(create, freeze) {
   2006   var handler = {
   2007     getPropertyDescriptor: function() { freeze(p); return {get: function(){}} },
   2008     fix: function() { return {} }
   2009   }
   2010   var p = create(handler)
   2011   var o = Object.create(p)
   2012   // Freeze while getting a property from prototype.
   2013   try { o.x } catch (e) { assertInstanceof(e, Error) }
   2014 })
   2015 
   2016 TestReentrantFix(function(create, freeze) {
   2017   var handler = {
   2018     get set() { freeze(p); return undefined },
   2019     fix: function() { return {} }
   2020   }
   2021   var p = create(handler)
   2022   // Freeze while getting set trap.
   2023   try { p.x = 4 } catch (e) { assertInstanceof(e, Error) }
   2024 })
   2025 
   2026 TestReentrantFix(function(create, freeze) {
   2027   var handler = {
   2028     set: function() { freeze(p); return true },
   2029     fix: function() { return {} }
   2030   }
   2031   var p = create(handler)
   2032   // Freeze while executing set trap.
   2033   try { p.x = 4 } catch (e) { assertInstanceof(e, Error) }
   2034 })
   2035 
   2036 TestReentrantFix(function(create, freeze) {
   2037   var handler = {
   2038     getOwnPropertyDescriptor: function() { freeze(p); return undefined },
   2039     fix: function() { return {} }
   2040   }
   2041   var p = create(handler)
   2042   // Freeze while executing default set trap.
   2043   try { p.x } catch (e) { assertInstanceof(e, Error) }
   2044 })
   2045 
   2046 TestReentrantFix(function(create, freeze) {
   2047   var handler = {
   2048     getPropertyDescriptor: function() { freeze(p); return {set: function(){}} },
   2049     fix: function() { return {} }
   2050   }
   2051   var p = create(handler)
   2052   var o = Object.create(p)
   2053   // Freeze while setting a property in prototype, dropping the property!
   2054   try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
   2055 })
   2056 
   2057 TestReentrantFix(function(create, freeze) {
   2058   var handler = {
   2059     getPropertyDescriptor: function() { freeze(p); return {set: function(){}} },
   2060     fix: function() { return {x: {get: function(){}}} }
   2061   }
   2062   var p = create(handler)
   2063   var o = Object.create(p)
   2064   // Freeze while setting a property in prototype, making it read-only!
   2065   try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
   2066 })
   2067 
   2068 TestReentrantFix(function(create, freeze) {
   2069   var handler = {
   2070     get fix() { freeze(p); return function(){} }
   2071   }
   2072   var p = create(handler)
   2073   // Freeze while getting fix trap.
   2074   try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) }
   2075   p = create(handler)
   2076   try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) }
   2077   p = create(handler)
   2078   try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) }
   2079 })
   2080 
   2081 TestReentrantFix(function(create, freeze) {
   2082   var handler = {
   2083     fix: function() { freeze(p); return {} }
   2084   }
   2085   var p = create(handler)
   2086   // Freeze while executing fix trap.
   2087   try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) }
   2088   p = create(handler)
   2089   try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) }
   2090   p = create(handler)
   2091   try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) }
   2092 })
   2093 
   2094 
   2095 
   2096 // String conversion (Object.prototype.toString,
   2097 //                    Object.prototype.toLocaleString,
   2098 //                    Function.prototype.toString)
   2099 
   2100 var key
   2101 
   2102 function TestToString(handler) {
   2103   var p = Proxy.create(handler)
   2104   key = ""
   2105   assertEquals("[object Object]", Object.prototype.toString.call(p))
   2106   assertEquals("", key)
   2107   assertEquals("my_proxy", Object.prototype.toLocaleString.call(p))
   2108   assertEquals("toString", key)
   2109 
   2110   var f = Proxy.createFunction(handler, function() {})
   2111   key = ""
   2112   assertEquals("[object Function]", Object.prototype.toString.call(f))
   2113   assertEquals("", key)
   2114   assertEquals("my_proxy", Object.prototype.toLocaleString.call(f))
   2115   assertEquals("toString", key)
   2116   assertDoesNotThrow(function(){ Function.prototype.toString.call(f) })
   2117 
   2118   var o = Object.create(p)
   2119   key = ""
   2120   assertEquals("[object Object]", Object.prototype.toString.call(o))
   2121   assertEquals("", key)
   2122   assertEquals("my_proxy", Object.prototype.toLocaleString.call(o))
   2123   assertEquals("toString", key)
   2124 }
   2125 
   2126 TestToString({
   2127   get: function(r, k) { key = k; return function() { return "my_proxy" } }
   2128 })
   2129 
   2130 TestToString({
   2131   get: function(r, k) { return this.get2(r, k) },
   2132   get2: function(r, k) { key = k; return function() { return "my_proxy" } }
   2133 })
   2134 
   2135 TestToString(Proxy.create({
   2136   get: function(pr, pk) {
   2137     return function(r, k) { key = k; return function() { return "my_proxy" } }
   2138   }
   2139 }))
   2140 
   2141 
   2142 function TestToStringThrow(handler) {
   2143   var p = Proxy.create(handler)
   2144   assertEquals("[object Object]", Object.prototype.toString.call(p))
   2145   assertThrows(function(){ Object.prototype.toLocaleString.call(p) }, "myexn")
   2146 
   2147   var f = Proxy.createFunction(handler, function() {})
   2148   assertEquals("[object Function]", Object.prototype.toString.call(f))
   2149   assertThrows(function(){ Object.prototype.toLocaleString.call(f) }, "myexn")
   2150 
   2151   var o = Object.create(p)
   2152   assertEquals("[object Object]", Object.prototype.toString.call(o))
   2153   assertThrows(function(){ Object.prototype.toLocaleString.call(o) }, "myexn")
   2154 }
   2155 
   2156 TestToStringThrow({
   2157   get: function(r, k) { throw "myexn" }
   2158 })
   2159 
   2160 TestToStringThrow({
   2161   get: function(r, k) { return function() { throw "myexn" } }
   2162 })
   2163 
   2164 TestToStringThrow({
   2165   get: function(r, k) { return this.get2(r, k) },
   2166   get2: function(r, k) { throw "myexn" }
   2167 })
   2168 
   2169 TestToStringThrow(Proxy.create({
   2170   get: function(pr, pk) { throw "myexn" }
   2171 }))
   2172 
   2173 TestToStringThrow(Proxy.create({
   2174   get: function(pr, pk) {
   2175     return function(r, k) { throw "myexn" }
   2176   }
   2177 }))
   2178 
   2179 
   2180 
   2181 // Value conversion (Object.prototype.toValue)
   2182 
   2183 function TestValueOf(handler) {
   2184   TestWithProxies(TestValueOf2, handler)
   2185 }
   2186 
   2187 function TestValueOf2(create, handler) {
   2188   var p = create(handler)
   2189   assertSame(p, Object.prototype.valueOf.call(p))
   2190 }
   2191 
   2192 TestValueOf({})
   2193 
   2194 
   2195 
   2196 // Enumerability (Object.prototype.propertyIsEnumerable)
   2197 
   2198 var key
   2199 
   2200 function TestIsEnumerable(handler) {
   2201   TestWithProxies(TestIsEnumerable2, handler)
   2202 }
   2203 
   2204 function TestIsEnumerable2(create, handler) {
   2205   var p = create(handler)
   2206   assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a"))
   2207   assertEquals("a", key)
   2208   assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2))
   2209   assertEquals("2", key)
   2210   assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z"))
   2211   assertEquals("z", key)
   2212 
   2213   var o = Object.create(p)
   2214   key = ""
   2215   assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a"))
   2216   assertEquals("", key)  // trap not invoked
   2217 }
   2218 
   2219 TestIsEnumerable({
   2220   getOwnPropertyDescriptor: function(k) {
   2221     key = k; return {enumerable: k < "z", configurable: true}
   2222   },
   2223 })
   2224 
   2225 TestIsEnumerable({
   2226   getOwnPropertyDescriptor: function(k) {
   2227     return this.getOwnPropertyDescriptor2(k)
   2228   },
   2229   getOwnPropertyDescriptor2: function(k) {
   2230     key = k; return {enumerable: k < "z", configurable: true}
   2231   },
   2232 })
   2233 
   2234 TestIsEnumerable({
   2235   getOwnPropertyDescriptor: function(k) {
   2236     key = k; return {get enumerable() { return k < "z" }, configurable: true}
   2237   },
   2238 })
   2239 
   2240 TestIsEnumerable(Proxy.create({
   2241   get: function(pr, pk) {
   2242     return function(k) {
   2243       key = k; return {enumerable: k < "z", configurable: true}
   2244     }
   2245   }
   2246 }))
   2247 
   2248 
   2249 function TestIsEnumerableThrow(handler) {
   2250   TestWithProxies(TestIsEnumerableThrow2, handler)
   2251 }
   2252 
   2253 function TestIsEnumerableThrow2(create, handler) {
   2254   var p = create(handler)
   2255   assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, "a") },
   2256     "myexn")
   2257   assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, 11) },
   2258     "myexn")
   2259 }
   2260 
   2261 TestIsEnumerableThrow({
   2262   getOwnPropertyDescriptor: function(k) { throw "myexn" }
   2263 })
   2264 
   2265 TestIsEnumerableThrow({
   2266   getOwnPropertyDescriptor: function(k) {
   2267     return this.getOwnPropertyDescriptor2(k)
   2268   },
   2269   getOwnPropertyDescriptor2: function(k) { throw "myexn" }
   2270 })
   2271 
   2272 TestIsEnumerableThrow({
   2273   getOwnPropertyDescriptor: function(k) {
   2274     return {get enumerable() { throw "myexn" }, configurable: true}
   2275   },
   2276 })
   2277 
   2278 TestIsEnumerableThrow(Proxy.create({
   2279   get: function(pr, pk) { throw "myexn" }
   2280 }))
   2281 
   2282 TestIsEnumerableThrow(Proxy.create({
   2283   get: function(pr, pk) {
   2284     return function(k) { throw "myexn" }
   2285   }
   2286 }))
   2287 
   2288 
   2289 
   2290 // Constructor functions with proxy prototypes.
   2291 
   2292 function TestConstructorWithProxyPrototype() {
   2293   TestWithProxies(TestConstructorWithProxyPrototype2, {})
   2294 }
   2295 
   2296 function TestConstructorWithProxyPrototype2(create, handler) {
   2297   function C() {};
   2298   C.prototype = create(handler);
   2299 
   2300   var o = new C;
   2301   assertSame(C.prototype, Object.getPrototypeOf(o));
   2302 }
   2303 
   2304 TestConstructorWithProxyPrototype();
   2305