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
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.
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.
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.
32 // Flags: --harmony-proxies --sim-stack-size=500 --turbo-deoptimization
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)
44 // Getting property descriptors (Object.getOwnPropertyDescriptor).
48 function TestGetOwnProperty(handler) {
49 TestWithProxies(TestGetOwnProperty2, handler)
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)
61 getOwnPropertyDescriptor: function(k) {
63 return {value: 42, configurable: true}
68 getOwnPropertyDescriptor: function(k) {
69 return this.getOwnPropertyDescriptor2(k)
71 getOwnPropertyDescriptor2: function(k) {
73 return {value: 42, configurable: true}
78 getOwnPropertyDescriptor: function(k) {
80 return {get value() { return 42 }, get configurable() { return true }}
84 TestGetOwnProperty(Proxy.create({
85 get: function(pr, pk) {
86 return function(k) { key = k; return {value: 42, configurable: true} }
91 function TestGetOwnPropertyThrow(handler) {
92 TestWithProxies(TestGetOwnPropertyThrow2, handler)
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")
101 TestGetOwnPropertyThrow({
102 getOwnPropertyDescriptor: function(k) { throw "myexn" }
105 TestGetOwnPropertyThrow({
106 getOwnPropertyDescriptor: function(k) {
107 return this.getPropertyDescriptor2(k)
109 getOwnPropertyDescriptor2: function(k) { throw "myexn" }
112 TestGetOwnPropertyThrow({
113 getOwnPropertyDescriptor: function(k) {
114 return {get value() { throw "myexn" }}
118 TestGetOwnPropertyThrow(Proxy.create({
119 get: function(pr, pk) {
120 return function(k) { throw "myexn" }
126 // Getters (dot, brackets).
130 function TestGet(handler) {
131 TestWithProxies(TestGet2, handler)
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)
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"))
164 get: function(r, k) { key = k; return 42 }
168 get: function(r, k) { return this.get2(r, k) },
169 get2: function(r, k) { key = k; return 42 }
173 getPropertyDescriptor: function(k) { key = k; return {value: 42} }
177 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
178 getPropertyDescriptor2: function(k) { key = k; return {value: 42} }
182 getPropertyDescriptor: function(k) {
184 return {get value() { return 42 }}
190 getPropertyDescriptor: function(k) { key = k; return {value: 42} }
193 TestGet(Proxy.create({
194 get: function(pr, pk) {
195 return function(r, k) { key = k; return 42 }
200 function TestGetCall(handler) {
201 TestWithProxies(TestGetCall2, handler)
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
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
244 get: function(r, k) { return function() { return 55 } }
248 get: function(r, k) { return this.get2(r, k) },
249 get2: function(r, k) { return function() { return 55 } }
253 getPropertyDescriptor: function(k) {
254 return {value: function() { return 55 }}
259 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
260 getPropertyDescriptor2: function(k) {
261 return {value: function() { return 55 }}
266 getPropertyDescriptor: function(k) {
267 return {get value() { return function() { return 55 } }}
273 getPropertyDescriptor: function(k) {
274 return {value: function() { return 55 }}
279 get: function(r, k) {
281 return function() { return 55 }
282 } else if (k == "withargs") {
283 return function(n, m) { return n + m * 2 }
285 return function() { return this.gg() }
290 TestGetCall(Proxy.create({
291 get: function(pr, pk) {
292 return function(r, k) { return function() { return 55 } }
297 function TestGetThrow(handler) {
298 TestWithProxies(TestGetThrow2, handler)
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")
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")
318 get: function(r, k) { throw "myexn" }
322 get: function(r, k) { return this.get2(r, k) },
323 get2: function(r, k) { throw "myexn" }
327 getPropertyDescriptor: function(k) { throw "myexn" }
331 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
332 getPropertyDescriptor2: function(k) { throw "myexn" }
336 getPropertyDescriptor: function(k) {
337 return {get value() { throw "myexn" }}
343 getPropertyDescriptor: function(k) { throw "myexn" }
346 TestGetThrow(Proxy.create({
347 get: function(pr, pk) { throw "myexn" }
350 TestGetThrow(Proxy.create({
351 get: function(pr, pk) {
352 return function(r, k) { throw "myexn" }
363 function TestSet(handler) {
364 TestWithProxies(TestSet2, handler)
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)
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)
388 set: function(r, k, v) { key = k; val = v; return true }
392 set: function(r, k, v) { return this.set2(r, k, v) },
393 set2: function(r, k, v) { key = k; val = v; return true }
397 getOwnPropertyDescriptor: function(k) { return {writable: true} },
398 defineProperty: function(k, desc) { key = k; val = desc.value }
402 getOwnPropertyDescriptor: function(k) {
403 return this.getOwnPropertyDescriptor2(k)
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 }
411 getOwnPropertyDescriptor: function(k) {
412 return {get writable() { return true }}
414 defineProperty: function(k, desc) { key = k; val = desc.value }
418 getOwnPropertyDescriptor: function(k) {
419 return {set: function(v) { key = k; val = v }}
424 getOwnPropertyDescriptor: function(k) { return null },
425 getPropertyDescriptor: function(k) { return {writable: true} },
426 defineProperty: function(k, desc) { key = k; val = desc.value }
430 getOwnPropertyDescriptor: function(k) { return null },
431 getPropertyDescriptor: function(k) {
432 return {get writable() { return true }}
434 defineProperty: function(k, desc) { key = k; val = desc.value }
438 getOwnPropertyDescriptor: function(k) { return null },
439 getPropertyDescriptor: function(k) {
440 return {set: function(v) { key = k; val = v }}
445 getOwnPropertyDescriptor: function(k) { return null },
446 getPropertyDescriptor: function(k) { return null },
447 defineProperty: function(k, desc) { key = k, val = desc.value }
450 TestSet(Proxy.create({
451 get: function(pr, pk) {
452 return function(r, k, v) { key = k; val = v; return true }
457 function TestSetThrow(handler) {
458 TestWithProxies(TestSetThrow2, handler)
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")
471 set: function(r, k, v) { throw "myexn" }
475 set: function(r, k, v) { return this.set2(r, k, v) },
476 set2: function(r, k, v) { throw "myexn" }
480 getOwnPropertyDescriptor: function(k) { throw "myexn" },
481 defineProperty: function(k, desc) { key = k; val = desc.value }
485 getOwnPropertyDescriptor: function(k) { return {writable: true} },
486 defineProperty: function(k, desc) { throw "myexn" }
490 getOwnPropertyDescriptor: function(k) {
491 return this.getOwnPropertyDescriptor2(k)
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 }
499 getOwnPropertyDescriptor: function(k) {
500 return this.getOwnPropertyDescriptor2(k)
502 getOwnPropertyDescriptor2: function(k) { return {writable: true} },
503 defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
504 defineProperty2: function(k, desc) { throw "myexn" }
508 getOwnPropertyDescriptor: function(k) { throw "myexn" },
509 defineProperty: function(k, desc) { key = k; val = desc.value }
513 getOwnPropertyDescriptor: function(k) {
514 return {get writable() { return true }}
516 defineProperty: function(k, desc) { throw "myexn" }
520 getOwnPropertyDescriptor: function(k) { throw "myexn" }
524 getOwnPropertyDescriptor: function(k) {
525 return {set: function(v) { throw "myexn" }}
530 getOwnPropertyDescriptor: function(k) { throw "myexn" },
531 getPropertyDescriptor: function(k) { return {writable: true} },
532 defineProperty: function(k, desc) { key = k; val = desc.value }
536 getOwnPropertyDescriptor: function(k) { return null },
537 getPropertyDescriptor: function(k) { throw "myexn" },
538 defineProperty: function(k, desc) { key = k; val = desc.value }
542 getOwnPropertyDescriptor: function(k) { return null },
543 getPropertyDescriptor: function(k) { return {writable: true} },
544 defineProperty: function(k, desc) { throw "myexn" }
548 getOwnPropertyDescriptor: function(k) { return null },
549 getPropertyDescriptor: function(k) {
550 return {get writable() { throw "myexn" }}
552 defineProperty: function(k, desc) { key = k; val = desc.value }
556 getOwnPropertyDescriptor: function(k) { return null },
557 getPropertyDescriptor: function(k) {
558 return {set: function(v) { throw "myexn" }}
563 getOwnPropertyDescriptor: function(k) { return null },
564 getPropertyDescriptor: function(k) { return null },
565 defineProperty: function(k, desc) { throw "myexn" }
568 TestSetThrow(Proxy.create({
569 get: function(pr, pk) { throw "myexn" }
572 TestSetThrow(Proxy.create({
573 get: function(pr, pk) {
574 return function(r, k, v) { throw "myexn" }
583 function TestSetForDerived(trap) {
584 TestWithProxies(TestSetForDerived2, trap)
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}})
593 assertEquals(48, o.x = 48)
594 assertEquals("", key) // trap not invoked
595 assertEquals(48, o.x)
597 assertEquals(47, o[1] = 47)
598 assertEquals("", key) // trap not invoked
599 assertEquals(47, o[1])
601 assertEquals(49, o.y = 49)
602 assertEquals("y", key)
603 assertEquals(49, o.y)
605 assertEquals(50, o[2] = 50)
606 assertEquals("2", key)
607 assertEquals(50, o[2])
609 assertEquals(44, o.p_writable = 44)
610 assertEquals("p_writable", key)
611 assertEquals(44, o.p_writable)
613 assertEquals(45, o.p_nonwritable = 45)
614 assertEquals("p_nonwritable", key)
615 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonwritable"))
617 assertThrows(function(){ "use strict"; o.p_nonwritable = 45 }, TypeError)
618 assertEquals("p_nonwritable", key)
619 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonwritable"))
622 assertEquals(46, o.p_setter = 46)
623 assertEquals("p_setter", key)
625 assertEquals(46, val) // written to parent
626 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setter"))
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"));
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"));
640 assertThrows(function(){ o.p_nonconf = 53 }, TypeError)
641 assertEquals("p_nonconf", key)
642 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_nonconf"));
644 assertThrows(function(){ o.p_throw = 51 }, "myexn")
645 assertEquals("p_throw", key)
646 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_throw"));
648 assertThrows(function(){ o.p_setterthrow = 52 }, "myexn")
649 assertEquals("p_setterthrow", key)
650 assertFalse(Object.prototype.hasOwnProperty.call(o, "p_setterthrow"));
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;
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 },
669 case "p_nosetter": return {
670 get: function() { return 1 },
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
682 // Evil proxy-induced side-effects shouldn't crash.
683 // TODO(rossberg): proper behaviour isn't really spec'ed yet, so ignore results.
685 TestWithProxies(function(create) {
688 getPropertyDescriptor: function() {
690 return (calls % 2 == 1)
691 ? {get: function() { return 5 }, configurable: true}
692 : {set: function() { return false }, configurable: true}
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) }
701 TestWithProxies(function(create) {
703 getPropertyDescriptor: function() {
704 Object.defineProperty(o, "x", {get: function() { return 5 }});
705 return {set: function() {}}
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) }
716 // TODO(rossberg): TestSetReject, returning false
717 // TODO(rossberg): TestGetProperty, TestSetProperty
721 // Property definition (Object.defineProperty and Object.defineProperties).
726 function TestDefine(handler) {
727 TestWithProxies(TestDefine2, handler)
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)
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)
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)
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)
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
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)
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())
772 assertEquals(p, Object.defineProperty(p, "zzz", {}))
773 assertEquals("zzz", key)
774 assertEquals(0, Object.getOwnPropertyNames(desc).length)
777 get: function(r, k) { return (k === "value") ? 77 : void 0 },
778 getOwnPropertyNames: function() { return ["value"] },
779 enumerate: function() { return ["value"] }
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)
790 blub: {get: function() { return true }},
791 '': {get value() { return 20 }},
792 last: {value: 21, configurable: true, mine: "eyes"}
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...
802 var props = {bla: {get value() { throw "myexn" }}}
803 assertThrows(function(){ Object.defineProperties(p, props) }, "myexn")
807 defineProperty: function(k, d) { key = k; desc = d; return true }
811 defineProperty: function(k, d) { return this.defineProperty2(k, d) },
812 defineProperty2: function(k, d) { key = k; desc = d; return true }
815 TestDefine(Proxy.create({
816 get: function(pr, pk) {
817 return function(k, d) { key = k; desc = d; return true }
822 function TestDefineThrow(handler) {
823 TestWithProxies(TestDefineThrow2, handler)
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")
832 get: function(r, k) { throw "myexn" },
833 getOwnPropertyNames: function() { return ["value"] }
835 assertThrows(function(){ Object.defineProperty(p, "p", d1) }, "myexn")
837 get: function(r, k) { return 77 },
838 getOwnPropertyNames: function() { throw "myexn" }
840 assertThrows(function(){ Object.defineProperty(p, "p", d2) }, "myexn")
842 var props = {bla: {get value() { throw "otherexn" }}}
843 assertThrows(function(){ Object.defineProperties(p, props) }, "otherexn")
847 defineProperty: function(k, d) { throw "myexn" }
851 defineProperty: function(k, d) { return this.defineProperty2(k, d) },
852 defineProperty2: function(k, d) { throw "myexn" }
855 TestDefineThrow(Proxy.create({
856 get: function(pr, pk) { throw "myexn" }
859 TestDefineThrow(Proxy.create({
860 get: function(pr, pk) {
861 return function(k, d) { throw "myexn" }
867 // Property deletion (delete).
871 function TestDelete(handler) {
872 TestWithProxies(TestDelete2, handler)
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)
884 assertEquals(false, delete p.z1)
885 assertEquals("z1", key)
886 assertEquals(false, delete p["z2"])
887 assertEquals("z2", key);
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)
898 assertThrows(function(){ delete p.z3 }, TypeError)
899 assertEquals("z3", key)
900 assertThrows(function(){ delete p["z4"] }, TypeError)
901 assertEquals("z4", key)
906 delete: function(k) { key = k; return k < "z" }
910 delete: function(k) { return this.delete2(k) },
911 delete2: function(k) { key = k; return k < "z" }
914 TestDelete(Proxy.create({
915 get: function(pr, pk) {
916 return function(k) { key = k; return k < "z" }
921 function TestDeleteThrow(handler) {
922 TestWithProxies(TestDeleteThrow2, handler)
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");
933 assertThrows(function(){ delete p.c }, "myexn")
934 assertThrows(function(){ delete p["d"] }, "myexn")
935 assertThrows(function(){ delete p[4] }, "myexn");
940 delete: function(k) { throw "myexn" }
944 delete: function(k) { return this.delete2(k) },
945 delete2: function(k) { throw "myexn" }
948 TestDeleteThrow(Proxy.create({
949 get: function(pr, pk) { throw "myexn" }
952 TestDeleteThrow(Proxy.create({
953 get: function(pr, pk) {
954 return function(k) { throw "myexn" }
960 // Property descriptors (Object.getOwnPropertyDescriptor).
962 function TestDescriptor(handler) {
963 TestWithProxies(TestDescriptor2, handler)
966 function TestDescriptor2(create, handler) {
967 var p = create(handler)
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}
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
981 if (prop != "mine") assertEquals(descs[i][prop], desc[prop])
983 assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent"))
988 defineProperty: function(k, d) { this["__" + k] = d; return true },
989 getOwnPropertyDescriptor: function(k) { return this["__" + k] }
993 defineProperty: function(k, d) { this["__" + k] = d; return true },
994 getOwnPropertyDescriptor: function(k) {
995 return this.getOwnPropertyDescriptor2(k)
997 getOwnPropertyDescriptor2: function(k) { return this["__" + k] }
1001 function TestDescriptorThrow(handler) {
1002 TestWithProxies(TestDescriptorThrow2, handler)
1005 function TestDescriptorThrow2(create, handler) {
1006 var p = create(handler)
1007 assertThrows(function(){ Object.getOwnPropertyDescriptor(p, "a") }, "myexn")
1010 TestDescriptorThrow({
1011 getOwnPropertyDescriptor: function(k) { throw "myexn" }
1014 TestDescriptorThrow({
1015 getOwnPropertyDescriptor: function(k) {
1016 return this.getOwnPropertyDescriptor2(k)
1018 getOwnPropertyDescriptor2: function(k) { throw "myexn" }
1025 function TestComparison(eq) {
1026 TestWithProxies(TestComparison2, eq)
1029 function TestComparison2(create, eq) {
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({}, {}))
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) })
1050 function TestTypeof() {
1051 assertEquals("object", typeof Proxy.create({}))
1052 assertTrue(typeof Proxy.create({}) == "object")
1053 assertTrue("object" == typeof Proxy.create({}))
1055 assertEquals("function", typeof Proxy.createFunction({}, function() {}))
1056 assertTrue(typeof Proxy.createFunction({}, function() {}) == "function")
1057 assertTrue("function" == typeof Proxy.createFunction({}, function() {}))
1064 // Membership test (in).
1068 function TestIn(handler) {
1069 TestWithProxies(TestIn2, handler)
1072 function TestIn2(create, handler) {
1073 var p = create(handler)
1074 assertTrue("a" in p)
1075 assertEquals("a", key)
1077 assertEquals("99", key)
1078 assertFalse("z" in p)
1079 assertEquals("z", key)
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)
1086 // Test compilation in conditionals.
1091 assertEquals("b", key)
1096 assertEquals("zz", key)
1101 assertEquals("c", key)
1103 if (!("zzz" in p)) {
1107 assertEquals("zzz", key)
1111 has: function(k) { key = k; return k < "z" }
1115 has: function(k) { return this.has2(k) },
1116 has2: function(k) { key = k; return k < "z" }
1120 getPropertyDescriptor: function(k) {
1121 key = k; return k < "z" ? {value: 42} : void 0
1126 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
1127 getPropertyDescriptor2: function(k) {
1128 key = k; return k < "z" ? {value: 42} : void 0
1133 getPropertyDescriptor: function(k) {
1134 key = k; return k < "z" ? {get value() { return 42 }} : void 0
1140 getPropertyDescriptor: function(k) {
1141 key = k; return k < "z" ? {value: 42} : void 0
1145 TestIn(Proxy.create({
1146 get: function(pr, pk) {
1147 return function(k) { key = k; return k < "z" }
1152 function TestInThrow(handler) {
1153 TestWithProxies(TestInThrow2, handler)
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")
1168 has: function(k) { throw "myexn" }
1172 has: function(k) { return this.has2(k) },
1173 has2: function(k) { throw "myexn" }
1177 getPropertyDescriptor: function(k) { throw "myexn" }
1181 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
1182 getPropertyDescriptor2: function(k) { throw "myexn" }
1187 getPropertyDescriptor: function(k) { throw "myexn" }
1190 TestInThrow(Proxy.create({
1191 get: function(pr, pk) { throw "myexn" }
1194 TestInThrow(Proxy.create({
1195 get: function(pr, pk) {
1196 return function(k) { throw "myexn" }
1201 function TestInForDerived(handler) {
1202 TestWithProxies(TestInForDerived2, handler)
1205 function TestInForDerived2(create, handler) {
1206 var p = create(handler)
1207 var o = Object.create(p)
1209 assertTrue("a" in o)
1210 assertEquals("a", key)
1212 assertEquals("99", key)
1213 assertFalse("z" in o)
1214 assertEquals("z", key)
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)
1225 assertEquals("b", key)
1230 assertEquals("zz", key)
1235 assertEquals("c", key)
1237 if (!("zzz" in o)) {
1241 assertEquals("zzz", key)
1245 getPropertyDescriptor: function(k) {
1246 key = k; return k < "z" ? {value: 42, configurable: true} : void 0
1251 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
1252 getPropertyDescriptor2: function(k) {
1253 key = k; return k < "z" ? {value: 42, configurable: true} : void 0
1258 getPropertyDescriptor: function(k) {
1260 return k < "z" ? {get value() { return 42 }, configurable: true} : void 0
1264 /* TODO(rossberg): this will work once we implement the newest proposal
1265 * regarding default traps for getPropertyDescriptor.
1267 getOwnPropertyDescriptor: function(k) {
1268 key = k; return k < "z" ? {value: 42, configurable: true} : void 0
1273 getOwnPropertyDescriptor: function(k) {
1274 return this.getOwnPropertyDescriptor2(k)
1276 getOwnPropertyDescriptor2: function(k) {
1277 key = k; return k < "z" ? {value: 42, configurable: true} : void 0
1282 getOwnPropertyDescriptor: function(k) {
1284 return k < "z" ? {get value() { return 42 }, configurable: true} : void 0
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
1299 // Property descriptor conversion.
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")
1312 function TestDescriptorGetOrder2(f, access) {
1315 assertEquals(access, descget)
1318 assertEquals(access, descget)
1320 assertFalse(!!f("z"))
1321 assertEquals("", descget)
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()
1333 has: function(attr) {
1338 case "configurable":
1354 // Own Properties (Object.prototype.hasOwnProperty).
1358 function TestHasOwn(handler) {
1359 TestWithProxies(TestHasOwn2, handler)
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)
1373 hasOwn: function(k) { key = k; return k < "z" }
1377 hasOwn: function(k) { return this.hasOwn2(k) },
1378 hasOwn2: function(k) { key = k; return k < "z" }
1382 getOwnPropertyDescriptor: function(k) {
1383 key = k; return k < "z" ? {value: 42} : void 0
1388 getOwnPropertyDescriptor: function(k) {
1389 return this.getOwnPropertyDescriptor2(k)
1391 getOwnPropertyDescriptor2: function(k) {
1392 key = k; return k < "z" ? {value: 42} : void 0
1397 getOwnPropertyDescriptor: function(k) {
1398 key = k; return k < "z" ? {get value() { return 42 }} : void 0
1404 getOwnPropertyDescriptor: function(k) {
1405 key = k; return k < "z" ? {value: 42} : void 0
1409 TestHasOwn(Proxy.create({
1410 get: function(pr, pk) {
1411 return function(k) { key = k; return k < "z" }
1416 function TestHasOwnThrow(handler) {
1417 TestWithProxies(TestHasOwnThrow2, handler)
1420 function TestHasOwnThrow2(create, handler) {
1421 var p = create(handler)
1422 assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, "a")},
1424 assertThrows(function(){ Object.prototype.hasOwnProperty.call(p, 99)},
1429 hasOwn: function(k) { throw "myexn" }
1433 hasOwn: function(k) { return this.hasOwn2(k) },
1434 hasOwn2: function(k) { throw "myexn" }
1438 getOwnPropertyDescriptor: function(k) { throw "myexn" }
1442 getOwnPropertyDescriptor: function(k) {
1443 return this.getOwnPropertyDescriptor2(k)
1445 getOwnPropertyDescriptor2: function(k) { throw "myexn" }
1450 getOwnPropertyDescriptor: function(k) { throw "myexn" }
1453 TestHasOwnThrow(Proxy.create({
1454 get: function(pr, pk) { throw "myexn" }
1457 TestHasOwnThrow(Proxy.create({
1458 get: function(pr, pk) {
1459 return function(k) { throw "myexn" }
1465 // Instanceof (instanceof)
1467 function TestProxyInstanceof() {
1469 var p1 = Proxy.create({})
1470 var p2 = Proxy.create({}, o1)
1471 var p3 = Proxy.create({}, p2)
1472 var o2 = Object.create(p2)
1474 var f0 = function() {}
1476 var f1 = function() {}
1478 var f2 = function() {}
1480 var f3 = function() {}
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)
1509 var f = Proxy.createFunction({}, function() {})
1510 assertTrue(f instanceof Function)
1513 TestProxyInstanceof()
1516 function TestInstanceofProxy() {
1517 var o0 = Object.create(null)
1519 var o2 = Object.create(o0)
1520 var o3 = Object.create(o1)
1521 var o4 = Object.create(o2)
1522 var o5 = Object.create(o3)
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() {})
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)
1570 var f = Proxy.createFunction({}, function() {})
1571 var ff = Proxy.createFunction(handler(Function), function() {})
1572 assertTrue(f instanceof Function)
1573 assertFalse(f instanceof ff)
1576 TestInstanceofProxy()
1580 // Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
1582 function TestPrototype() {
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)
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)
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))
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))
1645 // Property names (Object.getOwnPropertyNames, Object.keys).
1647 function TestPropertyNames(names, handler) {
1648 TestWithProxies(TestPropertyNames2, handler, names)
1651 function TestPropertyNames2(create, handler, names) {
1652 var p = create(handler)
1653 assertArrayEquals(names, Object.getOwnPropertyNames(p))
1656 TestPropertyNames([], {
1657 getOwnPropertyNames: function() { return [] }
1660 TestPropertyNames(["a", "zz", " ", "0", "toString"], {
1661 getOwnPropertyNames: function() { return ["a", "zz", " ", 0, "toString"] }
1664 TestPropertyNames(["throw", "function "], {
1665 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
1666 getOwnPropertyNames2: function() { return ["throw", "function "] }
1669 TestPropertyNames(["[object Object]"], {
1670 get getOwnPropertyNames() {
1671 return function() { return [{}] }
1676 function TestPropertyNamesThrow(handler) {
1677 TestWithProxies(TestPropertyNamesThrow2, handler)
1680 function TestPropertyNamesThrow2(create, handler) {
1681 var p = create(handler)
1682 assertThrows(function(){ Object.getOwnPropertyNames(p) }, "myexn")
1685 TestPropertyNamesThrow({
1686 getOwnPropertyNames: function() { throw "myexn" }
1689 TestPropertyNamesThrow({
1690 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
1691 getOwnPropertyNames2: function() { throw "myexn" }
1695 function TestKeys(names, handler) {
1696 TestWithProxies(TestKeys2, handler, names)
1699 function TestKeys2(create, handler, names) {
1700 var p = create(handler)
1701 assertArrayEquals(names, Object.keys(p))
1705 keys: function() { return [] }
1708 TestKeys(["a", "zz", " ", "0", "toString"], {
1709 keys: function() { return ["a", "zz", " ", 0, "toString"] }
1712 TestKeys(["throw", "function "], {
1713 keys: function() { return this.keys2() },
1714 keys2: function() { return ["throw", "function "] }
1717 TestKeys(["[object Object]"], {
1719 return function() { return [{}] }
1723 TestKeys(["a", "0"], {
1724 getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] },
1725 getOwnPropertyDescriptor: function(k) {
1726 return k == "" ? undefined : {enumerable: k.length == 1}
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)
1736 getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} }
1739 TestKeys(["a", "b", "c", "5"], {
1740 get getOwnPropertyNames() {
1741 return function() { return ["0", 4, "a", "b", "c", 5, "ety"] }
1743 get getOwnPropertyDescriptor() {
1744 return function(k) {
1745 return k == "ety" ? undefined : {enumerable: k >= "44"}
1751 get getOwnPropertyNames() {
1752 return function() { return ["a", "b", "c"] }
1754 getOwnPropertyDescriptor: function(k) { return {} }
1758 function TestKeysThrow(handler) {
1759 TestWithProxies(TestKeysThrow2, handler)
1762 function TestKeysThrow2(create, handler) {
1763 var p = create(handler)
1764 assertThrows(function(){ Object.keys(p) }, "myexn")
1768 keys: function() { throw "myexn" }
1772 keys: function() { return this.keys2() },
1773 keys2: function() { throw "myexn" }
1777 getOwnPropertyNames: function() { throw "myexn" },
1778 getOwnPropertyDescriptor: function(k) { return true }
1782 getOwnPropertyNames: function() { return [1, 2] },
1783 getOwnPropertyDescriptor: function(k) { throw "myexn" }
1787 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
1788 getOwnPropertyNames2: function() { throw "myexn" },
1792 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
1793 getOwnPropertyNames2: function() { return [1, 2] },
1794 getOwnPropertyDescriptor: function(k) {
1795 return this.getOwnPropertyDescriptor2(k)
1797 getOwnPropertyDescriptor2: function(k) { throw "myexn" }
1801 get getOwnPropertyNames() { throw "myexn" }
1805 get getOwnPropertyNames() {
1806 return function() { throw "myexn" }
1811 get getOwnPropertyNames() {
1812 return function() { return [1, 2] }
1814 getOwnPropertyDescriptor: function(k) { throw "myexn" }
1819 // Fixing (Object.freeze, Object.seal, Object.preventExtensions,
1820 // Object.isFrozen, Object.isSealed, Object.isExtensible)
1822 function TestFix(names, handler) {
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))
1830 var p1 = Proxy.create(handler, proto)
1831 assertFixing(p1, false, false, true)
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)
1840 var desc = Object.getOwnPropertyDescriptor(p1, n)
1841 if (desc !== undefined) assertFalse(desc.configurable)
1844 var p2 = Proxy.create(handler, proto)
1845 assertFixing(p2, false, false, true)
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)
1854 var desc = Object.getOwnPropertyDescriptor(p2, n)
1855 if (desc !== undefined) assertFalse(desc.writable)
1856 if (desc !== undefined) assertFalse(desc.configurable)
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)
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)
1874 assertFixing(p, false, false, true)
1875 assertFixing(o, true, true, false)
1879 fix: function() { return {} }
1882 TestFix(["a", "b", "c", "3", "zz"], {
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}
1895 fix: function() { return this.fix2() },
1897 return {a: {value: 4, writable: true, configurable: true, enumerable: true}}
1904 return {b: {configurable: true, writable: true, enumerable: true}}
1910 function TestFixFunction(fix) {
1911 var f1 = Proxy.createFunction({
1912 fix: function() { return {} }
1915 assertEquals(0, f1.length)
1917 var f2 = Proxy.createFunction({
1918 fix: function() { return {length: {value: 3}} }
1921 assertEquals(3, f2.length)
1923 var f3 = Proxy.createFunction({
1924 fix: function() { return {length: {value: "huh"}} }
1927 assertEquals(0, f1.length)
1930 TestFixFunction(Object.seal)
1931 TestFixFunction(Object.freeze)
1932 TestFixFunction(Object.preventExtensions)
1935 function TestFixThrow(handler) {
1936 TestWithProxies(TestFixThrow2, handler)
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")
1947 fix: function() { throw "myexn" }
1951 fix: function() { return this.fix2() },
1952 fix2: function() { throw "myexn" }
1956 get fix() { throw "myexn" }
1961 return function() { throw "myexn" }
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)
1975 TestReentrantFix(function(create, freeze) {
1977 get get() { freeze(p); return undefined },
1978 fix: function() { return {} }
1980 var p = create(handler)
1981 // Freeze while getting get trap.
1982 try { p.x } catch (e) { assertInstanceof(e, Error) }
1985 TestReentrantFix(function(create, freeze) {
1987 get: function() { freeze(p); return 3 },
1988 fix: function() { return {} }
1990 var p = create(handler)
1991 // Freeze while executing get trap.
1992 try { p.x } catch (e) { assertInstanceof(e, Error) }
1995 TestReentrantFix(function(create, freeze) {
1997 getPropertyDescriptor: function() { freeze(p); return undefined },
1998 fix: function() { return {} }
2000 var p = create(handler)
2001 // Freeze while executing default get trap.
2002 try { p.x } catch (e) { assertInstanceof(e, Error) }
2005 TestReentrantFix(function(create, freeze) {
2007 getPropertyDescriptor: function() { freeze(p); return {get: function(){}} },
2008 fix: function() { return {} }
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) }
2016 TestReentrantFix(function(create, freeze) {
2018 get set() { freeze(p); return undefined },
2019 fix: function() { return {} }
2021 var p = create(handler)
2022 // Freeze while getting set trap.
2023 try { p.x = 4 } catch (e) { assertInstanceof(e, Error) }
2026 TestReentrantFix(function(create, freeze) {
2028 set: function() { freeze(p); return true },
2029 fix: function() { return {} }
2031 var p = create(handler)
2032 // Freeze while executing set trap.
2033 try { p.x = 4 } catch (e) { assertInstanceof(e, Error) }
2036 TestReentrantFix(function(create, freeze) {
2038 getOwnPropertyDescriptor: function() { freeze(p); return undefined },
2039 fix: function() { return {} }
2041 var p = create(handler)
2042 // Freeze while executing default set trap.
2043 try { p.x } catch (e) { assertInstanceof(e, Error) }
2046 TestReentrantFix(function(create, freeze) {
2048 getPropertyDescriptor: function() { freeze(p); return {set: function(){}} },
2049 fix: function() { return {} }
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) }
2057 TestReentrantFix(function(create, freeze) {
2059 getPropertyDescriptor: function() { freeze(p); return {set: function(){}} },
2060 fix: function() { return {x: {get: function(){}}} }
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) }
2068 TestReentrantFix(function(create, freeze) {
2070 get fix() { freeze(p); return function(){} }
2072 var p = create(handler)
2073 // Freeze while getting fix trap.
2074 try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) }
2076 try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) }
2078 try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) }
2081 TestReentrantFix(function(create, freeze) {
2083 fix: function() { freeze(p); return {} }
2085 var p = create(handler)
2086 // Freeze while executing fix trap.
2087 try { Object.freeze(p) } catch (e) { assertInstanceof(e, Error) }
2089 try { Object.seal(p) } catch (e) { assertInstanceof(e, Error) }
2091 try { Object.preventExtensions(p) } catch (e) { assertInstanceof(e, Error) }
2096 // String conversion (Object.prototype.toString,
2097 // Object.prototype.toLocaleString,
2098 // Function.prototype.toString)
2102 function TestToString(handler) {
2103 var p = Proxy.create(handler)
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)
2110 var f = Proxy.createFunction(handler, function() {})
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) })
2118 var o = Object.create(p)
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)
2127 get: function(r, k) { key = k; return function() { return "my_proxy" } }
2131 get: function(r, k) { return this.get2(r, k) },
2132 get2: function(r, k) { key = k; return function() { return "my_proxy" } }
2135 TestToString(Proxy.create({
2136 get: function(pr, pk) {
2137 return function(r, k) { key = k; return function() { return "my_proxy" } }
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")
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")
2151 var o = Object.create(p)
2152 assertEquals("[object Object]", Object.prototype.toString.call(o))
2153 assertThrows(function(){ Object.prototype.toLocaleString.call(o) }, "myexn")
2157 get: function(r, k) { throw "myexn" }
2161 get: function(r, k) { return function() { throw "myexn" } }
2165 get: function(r, k) { return this.get2(r, k) },
2166 get2: function(r, k) { throw "myexn" }
2169 TestToStringThrow(Proxy.create({
2170 get: function(pr, pk) { throw "myexn" }
2173 TestToStringThrow(Proxy.create({
2174 get: function(pr, pk) {
2175 return function(r, k) { throw "myexn" }
2181 // Value conversion (Object.prototype.toValue)
2183 function TestValueOf(handler) {
2184 TestWithProxies(TestValueOf2, handler)
2187 function TestValueOf2(create, handler) {
2188 var p = create(handler)
2189 assertSame(p, Object.prototype.valueOf.call(p))
2196 // Enumerability (Object.prototype.propertyIsEnumerable)
2200 function TestIsEnumerable(handler) {
2201 TestWithProxies(TestIsEnumerable2, handler)
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)
2213 var o = Object.create(p)
2215 assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a"))
2216 assertEquals("", key) // trap not invoked
2220 getOwnPropertyDescriptor: function(k) {
2221 key = k; return {enumerable: k < "z", configurable: true}
2226 getOwnPropertyDescriptor: function(k) {
2227 return this.getOwnPropertyDescriptor2(k)
2229 getOwnPropertyDescriptor2: function(k) {
2230 key = k; return {enumerable: k < "z", configurable: true}
2235 getOwnPropertyDescriptor: function(k) {
2236 key = k; return {get enumerable() { return k < "z" }, configurable: true}
2240 TestIsEnumerable(Proxy.create({
2241 get: function(pr, pk) {
2242 return function(k) {
2243 key = k; return {enumerable: k < "z", configurable: true}
2249 function TestIsEnumerableThrow(handler) {
2250 TestWithProxies(TestIsEnumerableThrow2, handler)
2253 function TestIsEnumerableThrow2(create, handler) {
2254 var p = create(handler)
2255 assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, "a") },
2257 assertThrows(function(){ Object.prototype.propertyIsEnumerable.call(p, 11) },
2261 TestIsEnumerableThrow({
2262 getOwnPropertyDescriptor: function(k) { throw "myexn" }
2265 TestIsEnumerableThrow({
2266 getOwnPropertyDescriptor: function(k) {
2267 return this.getOwnPropertyDescriptor2(k)
2269 getOwnPropertyDescriptor2: function(k) { throw "myexn" }
2272 TestIsEnumerableThrow({
2273 getOwnPropertyDescriptor: function(k) {
2274 return {get enumerable() { throw "myexn" }, configurable: true}
2278 TestIsEnumerableThrow(Proxy.create({
2279 get: function(pr, pk) { throw "myexn" }
2282 TestIsEnumerableThrow(Proxy.create({
2283 get: function(pr, pk) {
2284 return function(k) { throw "myexn" }
2290 // Constructor functions with proxy prototypes.
2292 function TestConstructorWithProxyPrototype() {
2293 TestWithProxies(TestConstructorWithProxyPrototype2, {})
2296 function TestConstructorWithProxyPrototype2(create, handler) {
2298 C.prototype = create(handler);
2301 assertSame(C.prototype, Object.getPrototypeOf(o));
2304 TestConstructorWithProxyPrototype();