blob: 640033d9cc4a1f1081d69d5d5977308ca4bd63a5 [file] [log] [blame]
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001// Flags: --harmony-proxies
2
3// Copyright 2008 the V8 project authors. All rights reserved.
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following
12// disclaimer in the documentation and/or other materials provided
13// with the distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived
16// from this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
31// TODO(rossberg): test exception cases.
32
33
34// Getters.
35
36function TestGet(handler) {
37 var o = Proxy.create(handler)
38 assertEquals(42, o.a)
39 assertEquals(42, o["b"])
40}
41
42TestGet({
43 get: function(r, k) { return 42 }
44})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000045
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000046TestGet({
47 get: function(r, k) { return this.get2(r, k) },
48 get2: function(r, k) { return 42 }
49})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000050
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000051TestGet({
52 getPropertyDescriptor: function(k) { return {value: 42} }
53})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000054
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000055TestGet({
56 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
57 getPropertyDescriptor2: function(k) { return {value: 42} }
58})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000059
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000060TestGet({
61 getPropertyDescriptor: function(k) {
62 return {get value() { return 42 }}
63 }
64})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000065
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000066TestGet({
67 get: undefined,
68 getPropertyDescriptor: function(k) { return {value: 42} }
69})
70
71TestGet(Proxy.create({
72 get: function(pr, pk) {
73 return function(r, k) { return 42 }
74 }
75}))
76
77
78function TestGetCall(handler) {
79 var p = Proxy.create(handler)
80 assertEquals(55, p.f())
81 assertEquals(55, p.f("unused", "arguments"))
82 assertEquals(55, p.f.call(p))
83 assertEquals(55, p.withargs(45, 5))
84 assertEquals(55, p.withargs.call(p, 11, 22))
85 assertEquals("6655", "66" + p) // calls p.toString
86}
87
88TestGetCall({
89 get: function(r, k) { return function() { return 55 } }
90})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000091
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000092TestGetCall({
93 get: function(r, k) { return this.get2(r, k) },
94 get2: function(r, k) { return function() { return 55 } }
95})
Ben Murdoch69a99ed2011-11-30 16:03:39 +000096
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000097TestGetCall({
98 getPropertyDescriptor: function(k) {
99 return {value: function() { return 55 }}
100 }
101})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000102
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000103TestGetCall({
104 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
105 getPropertyDescriptor2: function(k) {
106 return {value: function() { return 55 }}
107 }
108})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000109
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000110TestGetCall({
111 getPropertyDescriptor: function(k) {
112 return {get value() { return function() { return 55 } }}
113 }
114})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000115
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000116TestGetCall({
117 get: undefined,
118 getPropertyDescriptor: function(k) {
119 return {value: function() { return 55 }}
120 }
121})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000122
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000123TestGetCall({
124 get: function(r, k) {
125 if (k == "gg") {
126 return function() { return 55 }
127 } else if (k == "withargs") {
128 return function(n, m) { return n + m * 2 }
129 } else {
130 return function() { return this.gg() }
131 }
132 }
133})
134
135TestGetCall(Proxy.create({
136 get: function(pr, pk) {
137 return function(r, k) { return function() { return 55 } }
138 }
139}))
140
141
142
143// Setters.
144
145var key
146var val
147function TestSet(handler) {
148 var o = Proxy.create(handler)
149 assertEquals(42, o.a = 42)
150 assertEquals("a", key)
151 assertEquals(42, val)
152 assertEquals(43, o["b"] = 43)
153 assertEquals("b", key)
154 assertEquals(43, val)
155}
156
157TestSet({
158 set: function(r, k, v) { key = k; val = v; return true }
159})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000160
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000161TestSet({
162 set: function(r, k, v) { return this.set2(r, k, v) },
163 set2: function(r, k, v) { key = k; val = v; return true }
164})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000165
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000166TestSet({
167 getOwnPropertyDescriptor: function(k) { return {writable: true} },
168 defineProperty: function(k, desc) { key = k; val = desc.value }
169})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000170
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000171TestSet({
172 getOwnPropertyDescriptor: function(k) {
173 return this.getOwnPropertyDescriptor2(k)
174 },
175 getOwnPropertyDescriptor2: function(k) { return {writable: true} },
176 defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
177 defineProperty2: function(k, desc) { key = k; val = desc.value }
178})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000179
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000180TestSet({
181 getOwnPropertyDescriptor: function(k) {
182 return {get writable() { return true }}
183 },
184 defineProperty: function(k, desc) { key = k; val = desc.value }
185})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000186
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000187TestSet({
188 getOwnPropertyDescriptor: function(k) {
189 return {set: function(v) { key = k; val = v }}
190 }
191})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000192
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000193TestSet({
194 getOwnPropertyDescriptor: function(k) { return null },
195 getPropertyDescriptor: function(k) { return {writable: true} },
196 defineProperty: function(k, desc) { key = k; val = desc.value }
197})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000198
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000199TestSet({
200 getOwnPropertyDescriptor: function(k) { return null },
201 getPropertyDescriptor: function(k) {
202 return {get writable() { return true }}
203 },
204 defineProperty: function(k, desc) { key = k; val = desc.value }
205})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000206
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000207TestSet({
208 getOwnPropertyDescriptor: function(k) { return null },
209 getPropertyDescriptor: function(k) {
210 return {set: function(v) { key = k; val = v }}
211 }
212})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000213
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000214TestSet({
215 getOwnPropertyDescriptor: function(k) { return null },
216 getPropertyDescriptor: function(k) { return null },
217 defineProperty: function(k, desc) { key = k, val = desc.value }
218})
219
220TestSet(Proxy.create({
221 get: function(pr, pk) {
222 return function(r, k, v) { key = k; val = v; return true }
223 }
224}))
225
226
227
228// Property definition (Object.defineProperty and Object.defineProperties).
229
230var key
231var desc
232function TestDefine(handler) {
233 var o = Proxy.create(handler)
234 assertEquals(o, Object.defineProperty(o, "a", {value: 44}))
235 assertEquals("a", key)
236 assertEquals(1, Object.getOwnPropertyNames(desc).length)
237 assertEquals(44, desc.value)
238
239 assertEquals(o, Object.defineProperty(o, "b", {value: 45, writable: false}))
240 assertEquals("b", key)
241 assertEquals(2, Object.getOwnPropertyNames(desc).length)
242 assertEquals(45, desc.value)
243 assertEquals(false, desc.writable)
244
245 assertEquals(o, Object.defineProperty(o, "c", {value: 46, enumerable: false}))
246 assertEquals("c", key)
247 assertEquals(2, Object.getOwnPropertyNames(desc).length)
248 assertEquals(46, desc.value)
249 assertEquals(false, desc.enumerable)
250
251 var attributes = {configurable: true, mine: 66, minetoo: 23}
252 assertEquals(o, Object.defineProperty(o, "d", attributes))
253 assertEquals("d", key)
254 // Modifying the attributes object after the fact should have no effect.
255 attributes.configurable = false
256 attributes.mine = 77
257 delete attributes.minetoo
258 assertEquals(3, Object.getOwnPropertyNames(desc).length)
259 assertEquals(true, desc.configurable)
260 assertEquals(66, desc.mine)
261 assertEquals(23, desc.minetoo)
262
263 assertEquals(o, Object.defineProperty(o, "e", {get: function(){ return 5 }}))
264 assertEquals("e", key)
265 assertEquals(1, Object.getOwnPropertyNames(desc).length)
266 assertEquals(5, desc.get())
267
268 assertEquals(o, Object.defineProperty(o, "zzz", {}))
269 assertEquals("zzz", key)
270 assertEquals(0, Object.getOwnPropertyNames(desc).length)
271
272// TODO(rossberg): This test requires [s in proxy] to be implemented first.
273// var d = Proxy.create({
274// get: function(r, k) { return (k === "value") ? 77 : void 0 },
275// getOwnPropertyNames: function() { return ["value"] }
276// })
277// assertEquals(1, Object.getOwnPropertyNames(d).length)
278// assertEquals(77, d.value)
279// assertEquals(o, Object.defineProperty(o, "p", d))
280// assertEquals("p", key)
281// assertEquals(1, Object.getOwnPropertyNames(desc).length)
282// assertEquals(77, desc.value)
283
284 var props = {
285 'bla': {},
286 blub: {get: function() { return true }},
287 '': {get value() { return 20 }},
288 last: {value: 21, configurable: true, mine: "eyes"}
289 }
290 Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false})
291 assertEquals(o, Object.defineProperties(o, props))
292 assertEquals("last", key)
293 assertEquals(2, Object.getOwnPropertyNames(desc).length)
294 assertEquals(21, desc.value)
295 assertEquals(true, desc.configurable)
296 assertEquals(undefined, desc.mine) // Arguably a bug in the spec...
297}
298
299TestDefine({
300 defineProperty: function(k, d) { key = k; desc = d; return true }
301})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000302
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000303TestDefine({
304 defineProperty: function(k, d) { return this.defineProperty2(k, d) },
305 defineProperty2: function(k, d) { key = k; desc = d; return true }
306})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000307
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000308TestDefine(Proxy.create({
309 get: function(pr, pk) {
310 return function(k, d) { key = k; desc = d; return true }
311 }
312}))
313
314
315
316// Property deletion (delete).
317
318var key
319function TestDelete(handler) {
320 var o = Proxy.create(handler)
321 assertEquals(true, delete o.a)
322 assertEquals("a", key)
323 assertEquals(true, delete o["b"])
324 assertEquals("b", key)
325
326 assertEquals(false, delete o.z1)
327 assertEquals("z1", key)
328 assertEquals(false, delete o["z2"])
329 assertEquals("z2", key);
330
331 (function() {
332 "use strict"
333 assertEquals(true, delete o.c)
334 assertEquals("c", key)
335 assertEquals(true, delete o["d"])
336 assertEquals("d", key)
337
338 assertThrows(function() { delete o.z3 }, TypeError)
339 assertEquals("z3", key)
340 assertThrows(function() { delete o["z4"] }, TypeError)
341 assertEquals("z4", key)
342 })()
343}
344
345TestDelete({
346 'delete': function(k) { key = k; return k < "z" }
347})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000348
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000349TestDelete({
350 'delete': function(k) { return this.delete2(k) },
351 delete2: function(k) { key = k; return k < "z" }
352})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000353
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000354TestDelete(Proxy.create({
355 get: function(pr, pk) {
356 return function(k) { key = k; return k < "z" }
357 }
358}))
359
360
361
362// Property descriptors (Object.getOwnPropertyDescriptor).
363
364function TestDescriptor(handler) {
365 var o = Proxy.create(handler)
366 var descs = [
367 {configurable: true},
368 {value: 34, enumerable: true, configurable: true},
369 {value: 3, writable: false, mine: "eyes", configurable: true},
370 {get value() { return 20 }, get configurable() { return true }},
371 {get: function() { "get" }, set: function() { "set" }, configurable: true}
372 ]
373 for (var i = 0; i < descs.length; ++i) {
374 assertEquals(o, Object.defineProperty(o, i, descs[i]))
375 var desc = Object.getOwnPropertyDescriptor(o, i)
376 for (p in descs[i]) {
377 // TODO(rossberg): Ignore user attributes as long as the spec isn't
378 // fixed suitably.
379 if (p != "mine") assertEquals(descs[i][p], desc[p])
380 }
381 assertEquals(undefined, Object.getOwnPropertyDescriptor(o, "absent"))
382 }
383}
384
385
386TestDescriptor({
387 defineProperty: function(k, d) { this["__" + k] = d; return true },
388 getOwnPropertyDescriptor: function(k) { return this["__" + k] }
389})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000390
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000391TestDescriptor({
392 defineProperty: function(k, d) { this["__" + k] = d; return true },
393 getOwnPropertyDescriptor: function(k) {
394 return this.getOwnPropertyDescriptor2(k)
395 },
396 getOwnPropertyDescriptor2: function(k) { return this["__" + k] }
397})
398
399
400
401// Comparison.
402
403function TestComparison(eq) {
404 var o1 = Proxy.create({})
405 var o2 = Proxy.create({})
406
407 assertTrue(eq(o1, o1))
408 assertTrue(eq(o2, o2))
409 assertTrue(!eq(o1, o2))
410 assertTrue(!eq(o1, {}))
411 assertTrue(!eq({}, o2))
412 assertTrue(!eq({}, {}))
413}
414
415TestComparison(function(o1, o2) { return o1 == o2 })
416TestComparison(function(o1, o2) { return o1 === o2 })
417TestComparison(function(o1, o2) { return !(o1 != o2) })
418TestComparison(function(o1, o2) { return !(o1 !== o2) })
419
420
421
422// Type.
423
424assertEquals("object", typeof Proxy.create({}))
425assertTrue(typeof Proxy.create({}) == "object")
426assertTrue("object" == typeof Proxy.create({}))
427
428// No function proxies yet.
429
430
431
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000432// Membership test (in).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000433
434var key
435function TestIn(handler) {
436 var o = Proxy.create(handler)
437 assertTrue("a" in o)
438 assertEquals("a", key)
439 assertTrue(99 in o)
440 assertEquals("99", key)
441 assertFalse("z" in o)
442 assertEquals("z", key)
443
444 if ("b" in o) {
445 } else {
446 assertTrue(false)
447 }
448 assertEquals("b", key)
449
450 if ("zz" in o) {
451 assertTrue(false)
452 }
453 assertEquals("zz", key)
454
455 if (!("c" in o)) {
456 assertTrue(false)
457 }
458 assertEquals("c", key)
459
460 if (!("zzz" in o)) {
461 } else {
462 assertTrue(false)
463 }
464 assertEquals("zzz", key)
465}
466
467TestIn({
468 has: function(k) { key = k; return k < "z" }
469})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000470
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000471TestIn({
472 has: function(k) { return this.has2(k) },
473 has2: function(k) { key = k; return k < "z" }
474})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000475
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000476TestIn({
477 getPropertyDescriptor: function(k) {
478 key = k; return k < "z" ? {value: 42} : void 0
479 }
480})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000481
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000482TestIn({
483 getPropertyDescriptor: function(k) { return this.getPropertyDescriptor2(k) },
484 getPropertyDescriptor2: function(k) {
485 key = k; return k < "z" ? {value: 42} : void 0
486 }
487})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000488
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000489TestIn({
490 getPropertyDescriptor: function(k) {
491 key = k; return k < "z" ? {get value() { return 42 }} : void 0
492 }
493})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000494
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000495TestIn({
496 get: undefined,
497 getPropertyDescriptor: function(k) {
498 key = k; return k < "z" ? {value: 42} : void 0
499 }
500})
501
502TestIn(Proxy.create({
503 get: function(pr, pk) {
504 return function(k) { key = k; return k < "z" }
505 }
506}))
507
508
509
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000510// Own Properties (Object.prototype.hasOwnProperty).
511
512var key
513function TestHasOwn(handler) {
514 var o = Proxy.create(handler)
515 assertTrue(Object.prototype.hasOwnProperty.call(o, "a"))
516 assertEquals("a", key)
517 assertTrue(Object.prototype.hasOwnProperty.call(o, 99))
518 assertEquals("99", key)
519 assertFalse(Object.prototype.hasOwnProperty.call(o, "z"))
520 assertEquals("z", key)
521}
522
523TestHasOwn({
524 hasOwn: function(k) { key = k; return k < "z" }
525})
526
527TestHasOwn({
528 hasOwn: function(k) { return this.hasOwn2(k) },
529 hasOwn2: function(k) { key = k; return k < "z" }
530})
531
532TestHasOwn({
533 getOwnPropertyDescriptor: function(k) {
534 key = k; return k < "z" ? {value: 42} : void 0
535 }
536})
537
538TestHasOwn({
539 getOwnPropertyDescriptor: function(k) {
540 return this.getOwnPropertyDescriptor2(k)
541 },
542 getOwnPropertyDescriptor2: function(k) {
543 key = k; return k < "z" ? {value: 42} : void 0
544 }
545})
546
547TestHasOwn({
548 getOwnPropertyDescriptor: function(k) {
549 key = k; return k < "z" ? {get value() { return 42 }} : void 0
550 }
551})
552
553TestHasOwn({
554 hasOwn: undefined,
555 getOwnPropertyDescriptor: function(k) {
556 key = k; return k < "z" ? {value: 42} : void 0
557 }
558})
559
560TestHasOwn(Proxy.create({
561 get: function(pr, pk) {
562 return function(k) { key = k; return k < "z" }
563 }
564}))
565
566
567
568// Instanceof (instanceof)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000569
570function TestInstanceof() {
571 var o = {}
572 var p1 = Proxy.create({})
573 var p2 = Proxy.create({}, o)
574 var p3 = Proxy.create({}, p2)
575
576 var f = function() {}
577 f.prototype = o
578 var f1 = function() {}
579 f1.prototype = p1
580 var f2 = function() {}
581 f2.prototype = p2
582
583 assertTrue(o instanceof Object)
584 assertFalse(o instanceof f)
585 assertFalse(o instanceof f1)
586 assertFalse(o instanceof f2)
587 assertFalse(p1 instanceof Object)
588 assertFalse(p1 instanceof f)
589 assertFalse(p1 instanceof f1)
590 assertFalse(p1 instanceof f2)
591 assertTrue(p2 instanceof Object)
592 assertTrue(p2 instanceof f)
593 assertFalse(p2 instanceof f1)
594 assertFalse(p2 instanceof f2)
595 assertTrue(p3 instanceof Object)
596 assertTrue(p3 instanceof f)
597 assertFalse(p3 instanceof f1)
598 assertTrue(p3 instanceof f2)
599}
600
601TestInstanceof()
602
603
604
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000605// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000606
607function TestPrototype() {
608 var o = {}
609 var p1 = Proxy.create({})
610 var p2 = Proxy.create({}, o)
611 var p3 = Proxy.create({}, p2)
612 var p4 = Proxy.create({}, 666)
613
614 assertSame(Object.getPrototypeOf(o), Object.prototype)
615 assertSame(Object.getPrototypeOf(p1), null)
616 assertSame(Object.getPrototypeOf(p2), o)
617 assertSame(Object.getPrototypeOf(p3), p2)
618 assertSame(Object.getPrototypeOf(p4), null)
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000619
620 assertTrue(Object.prototype.isPrototypeOf(o))
621 assertFalse(Object.prototype.isPrototypeOf(p1))
622 assertTrue(Object.prototype.isPrototypeOf(p2))
623 assertTrue(Object.prototype.isPrototypeOf(p3))
624 assertFalse(Object.prototype.isPrototypeOf(p4))
625 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o))
626 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p1))
627 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2))
628 assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3))
629 assertFalse(Object.prototype.isPrototypeOf.call(Object.prototype, p4))
630 assertFalse(Object.prototype.isPrototypeOf.call(o, o))
631 assertFalse(Object.prototype.isPrototypeOf.call(o, p1))
632 assertTrue(Object.prototype.isPrototypeOf.call(o, p2))
633 assertTrue(Object.prototype.isPrototypeOf.call(o, p3))
634 assertFalse(Object.prototype.isPrototypeOf.call(o, p4))
635 assertFalse(Object.prototype.isPrototypeOf.call(p1, p1))
636 assertFalse(Object.prototype.isPrototypeOf.call(p1, o))
637 assertFalse(Object.prototype.isPrototypeOf.call(p1, p2))
638 assertFalse(Object.prototype.isPrototypeOf.call(p1, p3))
639 assertFalse(Object.prototype.isPrototypeOf.call(p1, p4))
640 assertFalse(Object.prototype.isPrototypeOf.call(p2, p1))
641 assertFalse(Object.prototype.isPrototypeOf.call(p2, p2))
642 assertTrue(Object.prototype.isPrototypeOf.call(p2, p3))
643 assertFalse(Object.prototype.isPrototypeOf.call(p2, p4))
644 assertFalse(Object.prototype.isPrototypeOf.call(p3, p2))
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000645}
646
647TestPrototype()
648
649
650
651// Property names (Object.getOwnPropertyNames, Object.keys).
652
653function TestPropertyNames(names, handler) {
654 var p = Proxy.create(handler)
655 assertArrayEquals(names, Object.getOwnPropertyNames(p))
656}
657
658TestPropertyNames([], {
659 getOwnPropertyNames: function() { return [] }
660})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000661
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000662TestPropertyNames(["a", "zz", " ", "0"], {
663 getOwnPropertyNames: function() { return ["a", "zz", " ", 0] }
664})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000665
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000666TestPropertyNames(["throw", "function "], {
667 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
668 getOwnPropertyNames2: function() { return ["throw", "function "] }
669})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000670
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000671TestPropertyNames(["[object Object]"], {
672 get getOwnPropertyNames() {
673 return function() { return [{}] }
674 }
675})
676
677
678function TestKeys(names, handler) {
679 var p = Proxy.create(handler)
680 assertArrayEquals(names, Object.keys(p))
681}
682
683TestKeys([], {
684 keys: function() { return [] }
685})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000686
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000687TestKeys(["a", "zz", " ", "0"], {
688 keys: function() { return ["a", "zz", " ", 0] }
689})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000690
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000691TestKeys(["throw", "function "], {
692 keys: function() { return this.keys2() },
693 keys2: function() { return ["throw", "function "] }
694})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000695
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000696TestKeys(["[object Object]"], {
697 get keys() {
698 return function() { return [{}] }
699 }
700})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000701
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000702TestKeys(["a", "0"], {
703 getOwnPropertyNames: function() { return ["a", 23, "zz", "", 0] },
704 getOwnPropertyDescriptor: function(k) { return {enumerable: k.length == 1} }
705})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000706
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000707TestKeys(["23", "zz", ""], {
708 getOwnPropertyNames: function() { return this.getOwnPropertyNames2() },
709 getOwnPropertyNames2: function() { return ["a", 23, "zz", "", 0] },
710 getOwnPropertyDescriptor: function(k) {
711 return this.getOwnPropertyDescriptor2(k)
712 },
713 getOwnPropertyDescriptor2: function(k) { return {enumerable: k.length != 1} }
714})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000715
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000716TestKeys(["a", "b", "c", "5"], {
717 get getOwnPropertyNames() {
718 return function() { return ["0", 4, "a", "b", "c", 5] }
719 },
720 get getOwnPropertyDescriptor() {
721 return function(k) { return {enumerable: k >= "44"} }
722 }
723})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000724
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000725TestKeys([], {
726 get getOwnPropertyNames() {
727 return function() { return ["a", "b", "c"] }
728 },
729 getOwnPropertyDescriptor: function(k) { return {} }
730})
731
732
733
734// Fixing (Object.freeze, Object.seal, Object.preventExtensions,
735// Object.isFrozen, Object.isSealed, Object.isExtensible)
736
737function TestFix(names, handler) {
738 var proto = {p: 77}
739 var assertFixing = function(o, s, f, e) {
740 assertEquals(s, Object.isSealed(o))
741 assertEquals(f, Object.isFrozen(o))
742 assertEquals(e, Object.isExtensible(o))
743 }
744
745 var o1 = Proxy.create(handler, proto)
746 assertFixing(o1, false, false, true)
747 Object.seal(o1)
748 assertFixing(o1, true, names.length === 0, false)
749 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o1).sort())
750 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
751 Object.keys(o1).sort())
752 assertEquals(proto, Object.getPrototypeOf(o1))
753 assertEquals(77, o1.p)
754 for (var n in o1) {
755 var desc = Object.getOwnPropertyDescriptor(o1, n)
756 if (desc !== undefined) assertFalse(desc.configurable)
757 }
758
759 var o2 = Proxy.create(handler, proto)
760 assertFixing(o2, false, false, true)
761 Object.freeze(o2)
762 assertFixing(o2, true, true, false)
763 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o2).sort())
764 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
765 Object.keys(o2).sort())
766 assertEquals(proto, Object.getPrototypeOf(o2))
767 assertEquals(77, o2.p)
768 for (var n in o2) {
769 var desc = Object.getOwnPropertyDescriptor(o2, n)
770 if (desc !== undefined) assertFalse(desc.writable)
771 if (desc !== undefined) assertFalse(desc.configurable)
772 }
773
774 var o3 = Proxy.create(handler, proto)
775 assertFixing(o3, false, false, true)
776 Object.preventExtensions(o3)
777 assertFixing(o3, names.length === 0, names.length === 0, false)
778 assertArrayEquals(names.sort(), Object.getOwnPropertyNames(o3).sort())
779 assertArrayEquals(names.filter(function(x) {return x < "z"}).sort(),
780 Object.keys(o3).sort())
781 assertEquals(proto, Object.getPrototypeOf(o3))
782 assertEquals(77, o3.p)
783}
784
785TestFix([], {
786 fix: function() { return {} }
787})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000788
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000789TestFix(["a", "b", "c", "d", "zz"], {
790 fix: function() {
791 return {
792 a: {value: "a", writable: true, configurable: false, enumerable: true},
793 b: {value: 33, writable: false, configurable: false, enumerable: true},
794 c: {value: 0, writable: true, configurable: true, enumerable: true},
795 d: {value: true, writable: false, configurable: true, enumerable: true},
796 zz: {value: 0, enumerable: false}
797 }
798 }
799})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000800
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000801TestFix(["a"], {
802 fix: function() { return this.fix2() },
803 fix2: function() {
804 return {a: {value: 4, writable: true, configurable: true, enumerable: true}}
805 }
806})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000807
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000808TestFix(["b"], {
809 get fix() {
810 return function() {
811 return {b: {configurable: true, writable: true, enumerable: true}}
812 }
813 }
814})
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000815
816
817
818// String conversion (Object.prototype.toString, Object.prototype.toLocaleString)
819
820var key
821function TestToString(handler) {
822 var o = Proxy.create(handler)
823 key = ""
824 assertEquals("[object Object]", Object.prototype.toString.call(o))
825 assertEquals("", key)
826 assertEquals("my_proxy", Object.prototype.toLocaleString.call(o))
827 assertEquals("toString", key)
828}
829
830TestToString({
831 get: function(r, k) { key = k; return function() { return "my_proxy" } }
832})
833
834TestToString({
835 get: function(r, k) { return this.get2(r, k) },
836 get2: function(r, k) { key = k; return function() { return "my_proxy" } }
837})
838
839TestToString(Proxy.create({
840 get: function(pr, pk) {
841 return function(r, k) { key = k; return function() { return "my_proxy" } }
842 }
843}))
844
845
846
847// Value conversion (Object.prototype.toValue)
848
849function TestValueOf(handler) {
850 var o = Proxy.create(handler)
851 assertSame(o, Object.prototype.valueOf.call(o))
852}
853
854TestValueOf({})
855
856
857
858// Enumerability (Object.prototype.propertyIsEnumerable)
859
860var key
861function TestIsEnumerable(handler) {
862 var o = Proxy.create(handler)
863 assertTrue(Object.prototype.propertyIsEnumerable.call(o, "a"))
864 assertEquals("a", key)
865 assertTrue(Object.prototype.propertyIsEnumerable.call(o, 2))
866 assertEquals("2", key)
867 assertFalse(Object.prototype.propertyIsEnumerable.call(o, "z"))
868 assertEquals("z", key)
869}
870
871TestIsEnumerable({
872 getOwnPropertyDescriptor: function(k) {
873 key = k; return {enumerable: k < "z", configurable: true}
874 },
875})
876
877TestIsEnumerable({
878 getOwnPropertyDescriptor: function(k) {
879 return this.getOwnPropertyDescriptor2(k)
880 },
881 getOwnPropertyDescriptor2: function(k) {
882 key = k; return {enumerable: k < "z", configurable: true}
883 },
884})
885
886TestIsEnumerable({
887 getOwnPropertyDescriptor: function(k) {
888 key = k; return {get enumerable() { return k < "z" }, configurable: true}
889 },
890})
891
892TestIsEnumerable(Proxy.create({
893 get: function(pr, pk) {
894 return function(k) {
895 key = k; return {enumerable: k < "z", configurable: true}
896 }
897 }
898}))