Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / harmony / proxies.js
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 --turbo-deoptimization
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();