• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 --allow-natives-syntax
33
34
35// Helper.
36
37function TestWithProxies(test, x, y, z) {
38  // Separate function for nicer stack traces.
39  TestWithObjectProxy(test, x, y, z);
40  TestWithFunctionProxy(test, x, y, z);
41}
42
43function TestWithObjectProxy(test, x, y, z) {
44  test((handler) => { return new Proxy({}, handler) }, x, y, z)
45
46}
47
48function TestWithFunctionProxy(test, x, y, z) {
49  test((handler) => { return new Proxy(() => {}, handler) }, x, y, z)
50}
51
52// ---------------------------------------------------------------------------
53// Getting property descriptors (Object.getOwnPropertyDescriptor).
54
55var key
56
57function TestGetOwnProperty(handler) {
58  TestWithProxies(TestGetOwnProperty2, handler)
59}
60
61function TestGetOwnProperty2(create, handler) {
62  var p = create(handler)
63  assertEquals(42, Object.getOwnPropertyDescriptor(p, "a").value)
64  assertEquals("a", key)
65  assertEquals(42, Object.getOwnPropertyDescriptor(p, 99).value)
66  assertEquals("99", key)
67}
68
69TestGetOwnProperty({
70  getOwnPropertyDescriptor(target, k) {
71    key = k
72    return {value: 42, configurable: true}
73  }
74})
75
76TestGetOwnProperty({
77  getOwnPropertyDescriptor(target, k) {
78    return this.getOwnPropertyDescriptor2(k)
79  },
80  getOwnPropertyDescriptor2(k) {
81    key = k
82    return {value: 42, configurable: true}
83  }
84})
85
86TestGetOwnProperty({
87  getOwnPropertyDescriptor(target, k) {
88    key = k
89    return {get value() { return 42 }, get configurable() { return true }}
90  }
91})
92
93TestGetOwnProperty(new Proxy({}, {
94  get(target, pk, receiver) {
95    return function(t, k) { key = k; return {value: 42, configurable: true} }
96  }
97}))
98
99
100// ---------------------------------------------------------------------------
101function TestGetOwnPropertyThrow(handler) {
102  TestWithProxies(TestGetOwnPropertyThrow2, handler)
103}
104
105function TestGetOwnPropertyThrow2(create, handler) {
106  var p = create(handler)
107  assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn")
108  assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, 77), "myexn")
109}
110
111TestGetOwnPropertyThrow({
112  getOwnPropertyDescriptor: function(k) { throw "myexn" }
113})
114
115TestGetOwnPropertyThrow({
116  getOwnPropertyDescriptor: function(k) {
117    return this.getOwnPropertyDescriptor2(k)
118  },
119  getOwnPropertyDescriptor2: function(k) { throw "myexn" }
120})
121
122TestGetOwnPropertyThrow({
123  getOwnPropertyDescriptor: function(k) {
124    return {get value() { throw "myexn" }}
125  }
126})
127
128TestGetOwnPropertyThrow(new Proxy({}, {
129  get: function(pr, pk) {
130    return function(k) { throw "myexn" }
131  }
132}))
133
134
135// ---------------------------------------------------------------------------
136// Getters (dot, brackets).
137
138var key
139
140function TestGet(handler) {
141  TestWithProxies(TestGet2, handler)
142}
143
144function TestGet2(create, handler) {
145  var p = create(handler)
146  assertEquals(42, p.a)
147  assertEquals("a", key)
148  assertEquals(42, p["b"])
149  assertEquals("b", key)
150  assertEquals(42, p[99])
151  assertEquals("99", key)
152  assertEquals(42, (function(n) { return p[n] })("c"))
153  assertEquals("c", key)
154  assertEquals(42, (function(n) { return p[n] })(101))
155  assertEquals("101", key)
156
157  var o = Object.create(p, {x: {value: 88}})
158  assertEquals(42, o.a)
159  assertEquals("a", key)
160  assertEquals(42, o["b"])
161  assertEquals("b", key)
162  assertEquals(42, o[99])
163  assertEquals("99", key)
164  assertEquals(88, o.x)
165  assertEquals(88, o["x"])
166  assertEquals(42, (function(n) { return o[n] })("c"))
167  assertEquals("c", key)
168  assertEquals(42, (function(n) { return o[n] })(101))
169  assertEquals("101", key)
170  assertEquals(88, (function(n) { return o[n] })("x"))
171}
172
173TestGet({
174  get(t, k, r) { key = k; return 42 }
175})
176
177TestGet({
178  get(t, k, r) { return this.get2(r, k) },
179  get2(r, k) { key = k; return 42 }
180})
181
182TestGet(new Proxy({}, {
183  get(pt, pk, pr) {
184    return function(t, k, r) { key = k; return 42 }
185  }
186}))
187
188
189// ---------------------------------------------------------------------------
190function TestGetCall(handler) {
191  TestWithProxies(TestGetCall2, handler)
192}
193
194function TestGetCall2(create, handler) {
195  var p = create(handler)
196  assertEquals(55, p.f())
197  assertEquals(55, p["f"]())
198  assertEquals(55, p.f("unused", "arguments"))
199  assertEquals(55, p.f.call(p))
200  assertEquals(55, p["f"].call(p))
201  assertEquals(55, p[101].call(p))
202  assertEquals(55, p.withargs(45, 5))
203  assertEquals(55, p.withargs.call(p, 11, 22))
204  assertEquals(55, (function(n) { return p[n]() })("f"))
205  assertEquals(55, (function(n) { return p[n].call(p) })("f"))
206  assertEquals(55, (function(n) { return p[n](15, 20) })("withargs"))
207  assertEquals(55, (function(n) { return p[n].call(p, 13, 21) })("withargs"))
208  assertEquals("6655", "66" + p)  // calls p.toString
209
210  var o = Object.create(p, {g: {value: function(x) { return x + 88 }}})
211  assertEquals(55, o.f())
212  assertEquals(55, o["f"]())
213  assertEquals(55, o.f("unused", "arguments"))
214  assertEquals(55, o.f.call(o))
215  assertEquals(55, o.f.call(p))
216  assertEquals(55, o["f"].call(p))
217  assertEquals(55, o[101].call(p))
218  assertEquals(55, o.withargs(45, 5))
219  assertEquals(55, o.withargs.call(p, 11, 22))
220  assertEquals(90, o.g(2))
221  assertEquals(91, o.g.call(o, 3))
222  assertEquals(92, o.g.call(p, 4))
223  assertEquals(55, (function(n) { return o[n]() })("f"))
224  assertEquals(55, (function(n) { return o[n].call(o) })("f"))
225  assertEquals(55, (function(n) { return o[n](15, 20) })("withargs"))
226  assertEquals(55, (function(n) { return o[n].call(o, 13, 21) })("withargs"))
227  assertEquals(93, (function(n) { return o[n](5) })("g"))
228  assertEquals(94, (function(n) { return o[n].call(o, 6) })("g"))
229  assertEquals(95, (function(n) { return o[n].call(p, 7) })("g"))
230  assertEquals("6655", "66" + o)  // calls o.toString
231}
232
233TestGetCall({
234  get(t, k, r) { return () => { return 55 } }
235})
236
237TestGetCall({
238  get(t, k, r)  { return this.get2(t, k, r) },
239  get2(t, k, r) { return () => { return 55 } }
240})
241
242TestGetCall({
243  get(t, k, r) {
244    if (k == "gg") {
245      return () => { return 55 }
246    } else if (k == "withargs") {
247      return (n, m) => { return n + m * 2 }
248    } else {
249      return () => { return r.gg() }
250    }
251  }
252})
253
254TestGetCall(new Proxy({}, {
255  get(pt, pk, pr) {
256    return (t, k, r) => { return () => { return 55 } }
257  }
258}))
259
260
261// ---------------------------------------------------------------------------
262function TestGetThrow(handler) {
263  TestWithProxies(TestGetThrow2, handler)
264}
265
266function TestGetThrow2(create, handler) {
267  var p = create(handler)
268  assertThrowsEquals(function(){ p.a }, "myexn")
269  assertThrowsEquals(function(){ p["b"] }, "myexn")
270  assertThrowsEquals(function(){ p[3] }, "myexn")
271  assertThrowsEquals(function(){ (function(n) { p[n] })("c") }, "myexn")
272  assertThrowsEquals(function(){ (function(n) { p[n] })(99) }, "myexn")
273
274  var o = Object.create(p, {x: {value: 88}, '4': {value: 89}})
275  assertThrowsEquals(function(){ o.a }, "myexn")
276  assertThrowsEquals(function(){ o["b"] }, "myexn")
277  assertThrowsEquals(function(){ o[3] }, "myexn")
278  assertThrowsEquals(function(){ (function(n) { o[n] })("c") }, "myexn")
279  assertThrowsEquals(function(){ (function(n) { o[n] })(99) }, "myexn")
280}
281
282TestGetThrow({
283  get(r, k) { throw "myexn" }
284})
285
286TestGetThrow({
287  get(r, k) { return this.get2(r, k) },
288  get2(r, k) { throw "myexn" }
289})
290
291TestGetThrow(new Proxy({}, {
292  get(pr, pk) { throw "myexn" }
293}))
294
295TestGetThrow(new Proxy({}, {
296  get(pr, pk) {
297    return function(r, k) { throw "myexn" }
298  }
299}))
300
301
302// ---------------------------------------------------------------------------
303// Setters.
304
305var key
306var val
307
308function TestSet(handler) {
309  TestWithProxies(TestSet2, handler)
310}
311
312function TestSet2(create, handler) {
313  var p = create(handler)
314  assertEquals(42, p.a = 42)
315  assertEquals("a", key)
316  assertEquals(42, val)
317  assertEquals(43, p["b"] = 43)
318  assertEquals("b", key)
319  assertEquals(43, val)
320  assertEquals(44, p[77] = 44)
321  assertEquals("77", key)
322  assertEquals(44, val)
323
324  assertEquals(45, (function(n) { return p[n] = 45 })("c"))
325  assertEquals("c", key)
326  assertEquals(45, val)
327  assertEquals(46, (function(n) { return p[n] = 46 })(99))
328  assertEquals("99", key)
329  assertEquals(46, val)
330
331  assertEquals(47, p["0"] = 47)
332  assertEquals("0", key)
333  assertEquals(47, val)
334}
335
336TestSet({
337  set: function(r, k, v) { key = k; val = v; return true }
338})
339
340TestSet({
341  set: function(r, k, v) { return this.set2(r, k, v) },
342  set2: function(r, k, v) { key = k; val = v; return true }
343})
344
345TestSet(new Proxy({}, {
346  get(pk, pr) {
347    return (r, k, v) => { key = k; val = v; return true }
348  }
349}))
350
351
352// ---------------------------------------------------------------------------
353function TestSetThrow(handler) {
354  TestWithProxies(TestSetThrow2, handler)
355}
356
357function TestSetThrow2(create, handler) {
358  var p = create(handler)
359  assertThrowsEquals(function(){ p.a = 42 }, "myexn")
360  assertThrowsEquals(function(){ p["b"] = 42 }, "myexn")
361  assertThrowsEquals(function(){ p[22] = 42 }, "myexn")
362  assertThrowsEquals(function(){ (function(n) { p[n] = 45 })("c") }, "myexn")
363  assertThrowsEquals(function(){ (function(n) { p[n] = 46 })(99) }, "myexn")
364}
365
366TestSetThrow({
367  set: function(r, k, v) { throw "myexn" }
368})
369
370TestSetThrow({
371  set: function(r, k, v) { return this.set2(r, k, v) },
372  set2: function(r, k, v) { throw "myexn" }
373})
374
375TestSetThrow({
376  getOwnPropertyDescriptor: function(k) { throw "myexn" },
377  defineProperty: function(k, desc) { key = k; val = desc.value }
378})
379
380TestSetThrow({
381  getOwnPropertyDescriptor: function(k) {
382    return {configurable: true, writable: true}
383  },
384  defineProperty: function(k, desc) { throw "myexn" }
385})
386
387TestSetThrow({
388  getOwnPropertyDescriptor: function(k) {
389    return this.getOwnPropertyDescriptor2(k)
390  },
391  getOwnPropertyDescriptor2: function(k) { throw "myexn" },
392  defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
393  defineProperty2: function(k, desc) { key = k; val = desc.value }
394})
395
396TestSetThrow({
397  getOwnPropertyDescriptor: function(k) {
398    return this.getOwnPropertyDescriptor2(k)
399  },
400  getOwnPropertyDescriptor2: function(k) {
401    return {configurable: true, writable: true}
402  },
403  defineProperty: function(k, desc) { this.defineProperty2(k, desc) },
404  defineProperty2: function(k, desc) { throw "myexn" }
405})
406
407TestSetThrow({
408  getOwnPropertyDescriptor: function(k) { throw "myexn" },
409  defineProperty: function(k, desc) { key = k; val = desc.value }
410})
411
412TestSetThrow({
413  getOwnPropertyDescriptor: function(k) {
414    return {
415      get configurable() { return true },
416      get writable() { return true }
417    }
418  },
419  defineProperty: function(k, desc) { throw "myexn" }
420})
421
422TestSetThrow({
423  getOwnPropertyDescriptor: function(k) { throw "myexn" }
424})
425
426TestSetThrow({
427  getOwnPropertyDescriptor: function(k) { throw "myexn" },
428  defineProperty: function(k, desc) { key = k; val = desc.value }
429})
430
431TestSetThrow(new Proxy({}, {
432  get: function(pr, pk) { throw "myexn" }
433}))
434
435TestSetThrow(new Proxy({}, {
436  get: function(pr, pk) {
437    return function(r, k, v) { throw "myexn" }
438  }
439}))
440
441// ---------------------------------------------------------------------------
442
443// Evil proxy-induced side-effects shouldn't crash.
444TestWithProxies(function(create) {
445  var calls = 0
446  var handler = {
447    getPropertyDescriptor: function() {
448      ++calls
449      return (calls % 2 == 1)
450        ? {get: function() { return 5 }, configurable: true}
451        : {set: function() { return false }, configurable: true}
452    }
453  }
454  var p = create(handler)
455  var o = Object.create(p)
456  // Make proxy prototype property read-only after CanPut check.
457  try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
458})
459
460TestWithProxies(function(create) {
461  var handler = {
462    getPropertyDescriptor: function() {
463      Object.defineProperty(o, "x", {get: function() { return 5 }});
464      return {set: function() {}}
465    }
466  }
467  var p = create(handler)
468  var o = Object.create(p)
469  // Make object property read-only after CanPut check.
470  try { o.x = 4 } catch (e) { assertInstanceof(e, Error) }
471})
472
473
474// ---------------------------------------------------------------------------
475// Property definition (Object.defineProperty and Object.defineProperties).
476
477var key
478var desc
479
480function TestDefine(handler) {
481  TestWithProxies(TestDefine2, handler)
482}
483
484function TestDefine2(create, handler) {
485  var p = create(handler)
486  assertEquals(p, Object.defineProperty(p, "a", {value: 44}))
487  assertEquals("a", key)
488  assertEquals(1, Object.getOwnPropertyNames(desc).length)
489  assertEquals(44, desc.value)
490
491  assertEquals(p, Object.defineProperty(p, "b", {value: 45, writable: false}))
492  assertEquals("b", key)
493  assertEquals(2, Object.getOwnPropertyNames(desc).length)
494  assertEquals(45, desc.value)
495  assertEquals(false, desc.writable)
496
497  assertEquals(p, Object.defineProperty(p, "c", {value: 46, enumerable: false}))
498  assertEquals("c", key)
499  assertEquals(2, Object.getOwnPropertyNames(desc).length)
500  assertEquals(46, desc.value)
501  assertEquals(false, desc.enumerable)
502
503  assertEquals(p, Object.defineProperty(p, 101, {value: 47, enumerable: false}))
504  assertEquals("101", key)
505  assertEquals(2, Object.getOwnPropertyNames(desc).length)
506  assertEquals(47, desc.value)
507  assertEquals(false, desc.enumerable)
508
509  var attributes = {configurable: true, mine: 66, minetoo: 23}
510  assertEquals(p, Object.defineProperty(p, "d", attributes))
511  assertEquals("d", key);
512  // Modifying the attributes object after the fact should have no effect.
513  attributes.configurable = false
514  attributes.mine = 77
515  delete attributes.minetoo;
516  assertEquals(1, Object.getOwnPropertyNames(desc).length)
517  assertEquals(true, desc.configurable)
518  assertEquals(undefined, desc.mine)
519  assertEquals(undefined, desc.minetoo)
520
521  assertEquals(p, Object.defineProperty(p, "e", {get: function(){ return 5 }}))
522  assertEquals("e", key)
523  assertEquals(1, Object.getOwnPropertyNames(desc).length)
524  assertEquals(5, desc.get())
525
526  assertEquals(p, Object.defineProperty(p, "zzz", {}))
527  assertEquals("zzz", key)
528  assertEquals(0, Object.getOwnPropertyNames(desc).length)
529
530  var props = {
531    '11': {},
532    blub: {get: function() { return true }},
533    '': {get value() { return 20 }},
534    last: {value: 21, configurable: true, mine: "eyes"}
535  }
536  Object.defineProperty(props, "hidden", {value: "hidden", enumerable: false})
537  assertEquals(p, Object.defineProperties(p, props))
538  assertEquals("last", key)
539  assertEquals(2, Object.getOwnPropertyNames(desc).length)
540  assertEquals(21, desc.value)
541  assertEquals(true, desc.configurable)
542  assertEquals(undefined, desc.mine)  // Arguably a bug in the spec...
543
544  var props = {bla: {get value() { throw "myexn" }}}
545  assertThrowsEquals(function(){ Object.defineProperties(p, props) }, "myexn")
546}
547
548TestDefine({
549  defineProperty(t, k, d) { key = k; desc = d; return true }
550})
551
552TestDefine({
553  defineProperty(t, k, d) { return this.defineProperty2(k, d) },
554  defineProperty2(k, d) { key = k; desc = d; return true }
555})
556
557
558// ---------------------------------------------------------------------------
559function TestDefineThrow(handler) {
560  TestWithProxies(TestDefineThrow2, handler)
561}
562
563function TestDefineThrow2(create, handler) {
564  var p = create(handler)
565  assertThrowsEquals(() => Object.defineProperty(p, "a", {value: 44}), "myexn")
566  assertThrowsEquals(() => Object.defineProperty(p, 0, {value: 44}), "myexn")
567
568  var d1 = create({
569    get: function(r, k) { throw "myexn" },
570    getOwnPropertyNames: function() { return ["value"] }
571  })
572  assertThrowsEquals(function(){ Object.defineProperty(p, "p", d1) }, "myexn")
573  var d2 = create({
574    get: function(r, k) { return 77 },
575    getOwnPropertyNames: function() { throw "myexn" }
576  })
577  assertThrowsEquals(function(){ Object.defineProperty(p, "p", d2) }, "myexn")
578
579  var props = {bla: {get value() { throw "otherexn" }}}
580  assertThrowsEquals(() => Object.defineProperties(p, props), "otherexn")
581}
582
583TestDefineThrow({
584  defineProperty: function(k, d) { throw "myexn" }
585})
586
587TestDefineThrow({
588  defineProperty: function(k, d) { return this.defineProperty2(k, d) },
589  defineProperty2: function(k, d) { throw "myexn" }
590})
591
592TestDefineThrow(new Proxy({}, {
593  get: function(pr, pk) { throw "myexn" }
594}))
595
596TestDefineThrow(new Proxy({}, {
597  get: function(pr, pk) {
598    return function(k, d) { throw "myexn" }
599  }
600}))
601
602
603
604// ---------------------------------------------------------------------------
605// Property deletion (delete).
606
607var key
608
609function TestDelete(handler) {
610  TestWithProxies(TestDelete2, handler)
611}
612
613function TestDelete2(create, handler) {
614  var p = create(handler)
615  assertEquals(true, delete p.a)
616  assertEquals("a", key)
617  assertEquals(true, delete p["b"])
618  assertEquals("b", key)
619  assertEquals(true, delete p[1])
620  assertEquals("1", key)
621
622  assertEquals(false, delete p.z1)
623  assertEquals("z1", key)
624  assertEquals(false, delete p["z2"])
625  assertEquals("z2", key);
626
627  (function() {
628    "use strict"
629    assertEquals(true, delete p.c)
630    assertEquals("c", key)
631    assertEquals(true, delete p["d"])
632    assertEquals("d", key)
633    assertEquals(true, delete p[2])
634    assertEquals("2", key)
635
636    assertThrows(function(){ delete p.z3 }, TypeError)
637    assertEquals("z3", key)
638    assertThrows(function(){ delete p["z4"] }, TypeError)
639    assertEquals("z4", key)
640  })()
641}
642
643TestDelete({
644  deleteProperty(target, k) { key = k; return k < "z" }
645})
646
647TestDelete({
648  deleteProperty(target, k) { return this.delete2(k) },
649  delete2: function(k) { key = k; return k < "z" }
650})
651
652TestDelete(new Proxy({}, {
653  get(pt, pk, pr) {
654    return (target, k) => { key = k; return k < "z" }
655  }
656}))
657
658
659// ---------------------------------------------------------------------------
660function TestDeleteThrow(handler) {
661  TestWithProxies(TestDeleteThrow2, handler)
662}
663
664function TestDeleteThrow2(create, handler) {
665  var p = create(handler)
666  assertThrowsEquals(function(){ delete p.a }, "myexn")
667  assertThrowsEquals(function(){ delete p["b"] }, "myexn");
668  assertThrowsEquals(function(){ delete p[3] }, "myexn");
669
670  (function() {
671    "use strict"
672    assertThrowsEquals(function(){ delete p.c }, "myexn")
673    assertThrowsEquals(function(){ delete p["d"] }, "myexn")
674    assertThrowsEquals(function(){ delete p[4] }, "myexn");
675  })()
676}
677
678TestDeleteThrow({
679  deleteProperty(t, k) { throw "myexn" }
680})
681
682TestDeleteThrow({
683  deleteProperty(t, k) { return this.delete2(k) },
684  delete2(k) { throw "myexn" }
685})
686
687TestDeleteThrow(new Proxy({}, {
688  get(pt, pk, pr) { throw "myexn" }
689}))
690
691TestDeleteThrow(new Proxy({}, {
692  get(pt, pk, pr) {
693    return (k) => { throw "myexn" }
694  }
695}))
696
697
698// ---------------------------------------------------------------------------
699// Property descriptors (Object.getOwnPropertyDescriptor).
700
701function TestDescriptor(handler) {
702  TestWithProxies(TestDescriptor2, handler)
703}
704
705function TestDescriptor2(create, handler) {
706  var p = create(handler)
707  var descs = [
708    {configurable: true},
709    {value: 34, enumerable: true, configurable: true},
710    {value: 3, writable: false, mine: "eyes", configurable: true},
711    {get value() { return 20 }, get configurable() { return true }},
712    {get: function() { "get" }, set: function() { "set" }, configurable: true}
713  ]
714  for (var i = 0; i < descs.length; ++i) {
715    assertEquals(p, Object.defineProperty(p, i, descs[i]))
716    var desc = Object.getOwnPropertyDescriptor(p, i)
717    for (prop in descs[i]) {
718      // TODO(rossberg): Ignore user attributes as long as the spec isn't
719      // fixed suitably.
720      if (prop != "mine") assertEquals(descs[i][prop], desc[prop])
721    }
722    assertEquals(undefined, Object.getOwnPropertyDescriptor(p, "absent"))
723  }
724}
725
726TestDescriptor({
727  defineProperty(t, k, d) { this["__" + k] = d; return true },
728  getOwnPropertyDescriptor(t, k) { return this["__" + k] }
729})
730
731TestDescriptor({
732  defineProperty(t, k, d) { this["__" + k] = d; return true },
733  getOwnPropertyDescriptor(t, k) {
734    return this.getOwnPropertyDescriptor2(k)
735  },
736  getOwnPropertyDescriptor2: function(k) { return this["__" + k] }
737})
738
739
740// ---------------------------------------------------------------------------
741function TestDescriptorThrow(handler) {
742  TestWithProxies(TestDescriptorThrow2, handler)
743}
744
745function TestDescriptorThrow2(create, handler) {
746  var p = create(handler)
747  assertThrowsEquals(() => Object.getOwnPropertyDescriptor(p, "a"), "myexn")
748}
749
750TestDescriptorThrow({
751  getOwnPropertyDescriptor: function(k) { throw "myexn" }
752})
753
754TestDescriptorThrow({
755  getOwnPropertyDescriptor: function(k) {
756    return this.getOwnPropertyDescriptor2(k)
757  },
758  getOwnPropertyDescriptor2: function(k) { throw "myexn" }
759})
760
761
762
763// ---------------------------------------------------------------------------
764// Comparison.
765
766function TestComparison(eq) {
767  TestWithProxies(TestComparison2, eq)
768}
769
770function TestComparison2(create, eq) {
771  var p1 = create({})
772  var p2 = create({})
773
774  assertTrue(eq(p1, p1))
775  assertTrue(eq(p2, p2))
776  assertTrue(!eq(p1, p2))
777  assertTrue(!eq(p1, {}))
778  assertTrue(!eq({}, p2))
779  assertTrue(!eq({}, {}))
780}
781
782TestComparison(function(o1, o2) { return o1 == o2 })
783TestComparison(function(o1, o2) { return o1 === o2 })
784TestComparison(function(o1, o2) { return !(o1 != o2) })
785TestComparison(function(o1, o2) { return !(o1 !== o2) })
786
787
788
789// Type (typeof).
790
791function TestTypeof() {
792  assertEquals("object", typeof new Proxy({},{}))
793  assertTrue(typeof new Proxy({}, {}) == "object")
794  assertTrue("object" == typeof new Proxy({},{}))
795
796  assertEquals("function", typeof new Proxy(function() {}, {}))
797  assertTrue(typeof new Proxy(function() {}, {}) == "function")
798  assertTrue("function" == typeof new Proxy(function() {},{}))
799}
800
801TestTypeof()
802
803
804
805// ---------------------------------------------------------------------------
806// Membership test (in).
807
808var key
809
810function TestIn(handler) {
811  TestWithProxies(TestIn2, handler)
812}
813
814function TestIn2(create, handler) {
815  var p = create(handler)
816  assertTrue("a" in p)
817  assertEquals("a", key)
818  assertTrue(99 in p)
819  assertEquals("99", key)
820  assertFalse("z" in p)
821  assertEquals("z", key)
822
823  assertEquals(2, ("a" in p) ? 2 : 0)
824  assertEquals(0, !("a" in p) ? 2 : 0)
825  assertEquals(0, ("zzz" in p) ? 2 : 0)
826  assertEquals(2, !("zzz" in p) ? 2 : 0)
827
828  // Test compilation in conditionals.
829  if ("b" in p) {
830  } else {
831    assertTrue(false)
832  }
833  assertEquals("b", key)
834
835  if ("zz" in p) {
836    assertTrue(false)
837  }
838  assertEquals("zz", key)
839
840  if (!("c" in p)) {
841    assertTrue(false)
842  }
843  assertEquals("c", key)
844
845  if (!("zzz" in p)) {
846  } else {
847    assertTrue(false)
848  }
849  assertEquals("zzz", key)
850}
851
852TestIn({
853  has(t, k) { key = k; return k < "z" }
854})
855
856TestIn({
857  has(t, k) { return this.has2(k) },
858  has2(k) { key = k; return k < "z" }
859})
860
861TestIn(new Proxy({},{
862  get(pt, pk, pr) {
863    return (t, k) => { key = k; return k < "z" }
864  }
865}))
866
867
868// ---------------------------------------------------------------------------
869function TestInThrow(handler) {
870  TestWithProxies(TestInThrow2, handler)
871}
872
873function TestInThrow2(create, handler) {
874  var p = create(handler)
875  assertThrowsEquals(function(){ return "a" in p }, "myexn")
876  assertThrowsEquals(function(){ return 99 in p }, "myexn")
877  assertThrowsEquals(function(){ return !("a" in p) }, "myexn")
878  assertThrowsEquals(function(){ return ("a" in p) ? 2 : 3 }, "myexn")
879  assertThrowsEquals(function(){ if ("b" in p) {} }, "myexn")
880  assertThrowsEquals(function(){ if (!("b" in p)) {} }, "myexn")
881  assertThrowsEquals(function(){ if ("zzz" in p) {} }, "myexn")
882}
883
884TestInThrow({
885  has: function(k) { throw "myexn" }
886})
887
888TestInThrow({
889  has: function(k) { return this.has2(k) },
890  has2: function(k) { throw "myexn" }
891})
892
893TestInThrow(new Proxy({},{
894  get: function(pr, pk) { throw "myexn" }
895}))
896
897TestInThrow(new Proxy({},{
898  get: function(pr, pk) {
899    return function(k) { throw "myexn" }
900  }
901}))
902
903
904
905// ---------------------------------------------------------------------------
906// Own Properties (Object.prototype.hasOwnProperty).
907
908var key
909
910function TestHasOwn(handler) {
911  TestWithProxies(TestHasOwn2, handler)
912}
913
914function TestHasOwn2(create, handler) {
915  var p = create(handler)
916  assertTrue(Object.prototype.hasOwnProperty.call(p, "a"))
917  assertEquals("a", key)
918  assertTrue(Object.prototype.hasOwnProperty.call(p, 99))
919  assertEquals("99", key)
920  assertFalse(Object.prototype.hasOwnProperty.call(p, "z"))
921  assertEquals("z", key)
922}
923
924TestHasOwn({
925  getOwnPropertyDescriptor(t, k) {
926    key = k; if (k < "z") return {configurable: true}
927  },
928  has() { assertUnreachable() }
929})
930
931TestHasOwn({
932  getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) },
933  getOwnPropertyDescriptor2(k) {
934    key = k; if (k < "z") return {configurable: true}
935  }
936})
937
938
939
940// ---------------------------------------------------------------------------
941function TestHasOwnThrow(handler) {
942  TestWithProxies(TestHasOwnThrow2, handler)
943}
944
945function TestHasOwnThrow2(create, handler) {
946  var p = create(handler)
947  assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, "a")},
948    "myexn")
949  assertThrowsEquals(function(){ Object.prototype.hasOwnProperty.call(p, 99)},
950    "myexn")
951}
952
953TestHasOwnThrow({
954  getOwnPropertyDescriptor(t, k) { throw "myexn" }
955})
956
957TestHasOwnThrow({
958  getOwnPropertyDescriptor(t, k) { return this.getOwnPropertyDescriptor2(k) },
959  getOwnPropertyDescriptor2(k) { throw "myexn" }
960});
961
962
963// ---------------------------------------------------------------------------
964// Instanceof (instanceof)
965
966(function TestProxyInstanceof() {
967  var o1 = {}
968  var p1 = new Proxy({}, {})
969  var p2 = new Proxy(o1, {})
970  var p3 = new Proxy(p2, {})
971  var o2 = Object.create(p2)
972
973  var f0 = function() {}
974  f0.prototype = o1
975  var f1 = function() {}
976  f1.prototype = p1
977  var f2 = function() {}
978  f2.prototype = p2
979  var f3 = function() {}
980  f3.prototype = o2
981
982  assertTrue(o1 instanceof Object)
983  assertFalse(o1 instanceof f0)
984  assertFalse(o1 instanceof f1)
985  assertFalse(o1 instanceof f2)
986  assertFalse(o1 instanceof f3)
987  assertTrue(p1 instanceof Object)
988  assertFalse(p1 instanceof f0)
989  assertFalse(p1 instanceof f1)
990  assertFalse(p1 instanceof f2)
991  assertFalse(p1 instanceof f3)
992  assertTrue(p2 instanceof Object)
993  assertFalse(p2 instanceof f0)
994  assertFalse(p2 instanceof f1)
995  assertFalse(p2 instanceof f2)
996  assertFalse(p2 instanceof f3)
997  assertTrue(p3 instanceof Object)
998  assertFalse(p3 instanceof f0)
999  assertFalse(p3 instanceof f1)
1000  assertFalse(p3 instanceof f2)
1001  assertFalse(p3 instanceof f3)
1002  assertTrue(o2 instanceof Object)
1003  assertFalse(o2 instanceof f0)
1004  assertFalse(o2 instanceof f1)
1005  assertTrue(o2 instanceof f2)
1006  assertFalse(o2 instanceof f3)
1007
1008  var f = new Proxy(function() {}, {})
1009  assertTrue(f instanceof Function)
1010})();
1011
1012
1013(function TestInstanceofProxy() {
1014  var o0 = Object.create(null)
1015  var o1 = {}
1016  var o2 = Object.create(o0)
1017  var o3 = Object.create(o1)
1018  var o4 = Object.create(o2)
1019  var o5 = Object.create(o3)
1020
1021  function handler(o) { return {get: function() { return o } } }
1022  var f0 = new Proxy(function() {}, handler(o0))
1023  var f1 = new Proxy(function() {}, handler(o1))
1024  var f2 = new Proxy(function() {}, handler(o2))
1025  var f3 = new Proxy(function() {}, handler(o3))
1026  var f4 = new Proxy(function() {}, handler(o4))
1027  var f5 = new Proxy(function() {}, handler(o4))
1028
1029  assertFalse(null instanceof f0)
1030  assertFalse(o0 instanceof f0)
1031  assertFalse(o0 instanceof f1)
1032  assertFalse(o0 instanceof f2)
1033  assertFalse(o0 instanceof f3)
1034  assertFalse(o0 instanceof f4)
1035  assertFalse(o0 instanceof f5)
1036  assertFalse(o1 instanceof f0)
1037  assertFalse(o1 instanceof f1)
1038  assertFalse(o1 instanceof f2)
1039  assertFalse(o1 instanceof f3)
1040  assertFalse(o1 instanceof f4)
1041  assertFalse(o1 instanceof f5)
1042  assertTrue(o2 instanceof f0)
1043  assertFalse(o2 instanceof f1)
1044  assertFalse(o2 instanceof f2)
1045  assertFalse(o2 instanceof f3)
1046  assertFalse(o2 instanceof f4)
1047  assertFalse(o2 instanceof f5)
1048  assertFalse(o3 instanceof f0)
1049  assertTrue(o3 instanceof f1)
1050  assertFalse(o3 instanceof f2)
1051  assertFalse(o3 instanceof f3)
1052  assertFalse(o3 instanceof f4)
1053  assertFalse(o3 instanceof f5)
1054  assertTrue(o4 instanceof f0)
1055  assertFalse(o4 instanceof f1)
1056  assertTrue(o4 instanceof f2)
1057  assertFalse(o4 instanceof f3)
1058  assertFalse(o4 instanceof f4)
1059  assertFalse(o4 instanceof f5)
1060  assertFalse(o5 instanceof f0)
1061  assertTrue(o5 instanceof f1)
1062  assertFalse(o5 instanceof f2)
1063  assertTrue(o5 instanceof f3)
1064  assertFalse(o5 instanceof f4)
1065  assertFalse(o5 instanceof f5)
1066
1067  var f = new Proxy(function() {}, {})
1068  var ff = new Proxy(function() {}, handler(Function))
1069  assertTrue(f instanceof Function)
1070  assertFalse(f instanceof ff)
1071})();
1072
1073
1074// ---------------------------------------------------------------------------
1075// Prototype (Object.getPrototypeOf, Object.prototype.isPrototypeOf).
1076
1077(function TestPrototype() {
1078  var o1 = {}
1079  var p1 = new Proxy({}, {})
1080  var p2 = new Proxy(o1, {})
1081  var p3 = new Proxy(p2, {})
1082  var o2 = Object.create(p3)
1083
1084  assertSame(Object.getPrototypeOf(o1), Object.prototype)
1085  assertSame(Object.getPrototypeOf(p1), Object.prototype)
1086  assertSame(Object.getPrototypeOf(p2), Object.prototype)
1087  assertSame(Object.getPrototypeOf(p3), Object.prototype)
1088  assertSame(Object.getPrototypeOf(o2), p3)
1089
1090  assertTrue(Object.prototype.isPrototypeOf(o1))
1091  assertTrue(Object.prototype.isPrototypeOf(p1))
1092  assertTrue(Object.prototype.isPrototypeOf(p2))
1093  assertTrue(Object.prototype.isPrototypeOf(p3))
1094  assertTrue(Object.prototype.isPrototypeOf(o2))
1095  assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o1))
1096  assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p1))
1097  assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p2))
1098  assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, p3))
1099  assertTrue(Object.prototype.isPrototypeOf.call(Object.prototype, o2))
1100  assertFalse(Object.prototype.isPrototypeOf.call(o1, o1))
1101  assertFalse(Object.prototype.isPrototypeOf.call(o1, p1))
1102  assertFalse(Object.prototype.isPrototypeOf.call(o1, p2))
1103  assertFalse(Object.prototype.isPrototypeOf.call(o1, p3))
1104  assertFalse(Object.prototype.isPrototypeOf.call(o1, o2))
1105  assertFalse(Object.prototype.isPrototypeOf.call(p1, p1))
1106  assertFalse(Object.prototype.isPrototypeOf.call(p1, o1))
1107  assertFalse(Object.prototype.isPrototypeOf.call(p1, p2))
1108  assertFalse(Object.prototype.isPrototypeOf.call(p1, p3))
1109  assertFalse(Object.prototype.isPrototypeOf.call(p1, o2))
1110  assertFalse(Object.prototype.isPrototypeOf.call(p2, p1))
1111  assertFalse(Object.prototype.isPrototypeOf.call(p2, p2))
1112  assertFalse(Object.prototype.isPrototypeOf.call(p2, p3))
1113  assertFalse(Object.prototype.isPrototypeOf.call(p2, o2))
1114  assertFalse(Object.prototype.isPrototypeOf.call(p3, p2))
1115  assertTrue(Object.prototype.isPrototypeOf.call(p3, o2))
1116  assertFalse(Object.prototype.isPrototypeOf.call(o2, o1))
1117  assertFalse(Object.prototype.isPrototypeOf.call(o2, p1))
1118  assertFalse(Object.prototype.isPrototypeOf.call(o2, p2))
1119  assertFalse(Object.prototype.isPrototypeOf.call(o2, p3))
1120  assertFalse(Object.prototype.isPrototypeOf.call(o2, o2))
1121
1122  var f = new Proxy(function() {}, {})
1123  assertSame(Object.getPrototypeOf(f), Function.prototype)
1124  assertTrue(Object.prototype.isPrototypeOf(f))
1125  assertTrue(Object.prototype.isPrototypeOf.call(Function.prototype, f))
1126})();
1127
1128
1129// ---------------------------------------------------------------------------
1130function TestPropertyNamesThrow(handler) {
1131  TestWithProxies(TestPropertyNamesThrow2, handler)
1132}
1133
1134function TestPropertyNamesThrow2(create, handler) {
1135  var p = create(handler)
1136  assertThrowsEquals(function(){ Object.getOwnPropertyNames(p) }, "myexn")
1137}
1138
1139TestPropertyNamesThrow({
1140  ownKeys() { throw "myexn" }
1141})
1142
1143TestPropertyNamesThrow({
1144  ownKeys() { return this.getOwnPropertyNames2() },
1145  getOwnPropertyNames2() { throw "myexn" }
1146})
1147
1148// ---------------------------------------------------------------------------
1149
1150function TestKeys(names, handler) {
1151  var p = new Proxy({}, handler);
1152  assertArrayEquals(names, Object.keys(p))
1153}
1154
1155TestKeys([], {
1156  ownKeys() { return [] }
1157})
1158
1159TestKeys([], {
1160  ownKeys() { return ["a", "zz", " ", "0", "toString"] }
1161})
1162
1163TestKeys(["a", "zz", " ", "0", "toString"], {
1164  ownKeys() { return ["a", "zz", " ", "0", "toString"] },
1165  getOwnPropertyDescriptor(t, p) {
1166    return {configurable: true, enumerable: true}
1167  }
1168})
1169
1170TestKeys([], {
1171  ownKeys() { return this.keys2() },
1172  keys2() { return ["throw", "function "] }
1173})
1174
1175TestKeys(["throw", "function "], {
1176  ownKeys() { return this.keys2() },
1177  keys2() { return ["throw", "function "] },
1178  getOwnPropertyDescriptor(t, p) {
1179    return {configurable: true, enumerable: true}
1180  }
1181})
1182
1183TestKeys(["a", "0"], {
1184  ownKeys() { return ["a", "23", "zz", "", "0"] },
1185  getOwnPropertyDescriptor(t, k) {
1186    return k == "" ?
1187        undefined :
1188        { configurable: true, enumerable: k.length == 1}
1189  }
1190})
1191
1192TestKeys(["23", "zz", ""], {
1193  ownKeys() { return this.getOwnPropertyNames2() },
1194  getOwnPropertyNames2() { return ["a", "23", "zz", "", "0"] },
1195  getOwnPropertyDescriptor(t, k) {
1196    return this.getOwnPropertyDescriptor2(k)
1197  },
1198  getOwnPropertyDescriptor2(k) {
1199    return {configurable: true, enumerable: k.length != 1 }
1200  }
1201})
1202
1203TestKeys([], {
1204  get ownKeys() {
1205    return function() { return ["a", "b", "c"] }
1206  },
1207  getOwnPropertyDescriptor: function(k) { return {configurable: true} }
1208})
1209
1210
1211// ---------------------------------------------------------------------------
1212function TestKeysThrow(handler) {
1213  TestWithProxies(TestKeysThrow2, handler)
1214}
1215
1216function TestKeysThrow2(create, handler) {
1217  var p = create(handler);
1218  assertThrowsEquals(function(){ Object.keys(p) }, "myexn");
1219}
1220
1221TestKeysThrow({
1222  ownKeys() { throw "myexn" }
1223})
1224
1225TestKeysThrow({
1226  ownKeys() { return this.keys2() },
1227  keys2() { throw "myexn" }
1228})
1229
1230TestKeysThrow({
1231  ownKeys() { return ['1'] },
1232  getOwnPropertyDescriptor: function() { throw "myexn" },
1233})
1234
1235TestKeysThrow({
1236  ownKeys() { return this.getOwnPropertyNames2() },
1237  getOwnPropertyNames2() { return ['1', '2'] },
1238  getOwnPropertyDescriptor(k) {
1239    return this.getOwnPropertyDescriptor2(k)
1240  },
1241  getOwnPropertyDescriptor2(k) { throw "myexn" }
1242})
1243
1244TestKeysThrow({
1245  get ownKeys() { throw "myexn" }
1246})
1247
1248TestKeysThrow({
1249  get ownKeys() {
1250    return function() { throw "myexn" }
1251  },
1252})
1253
1254TestKeysThrow({
1255  get ownKeys() {
1256    return function() { return ['1', '2'] }
1257  },
1258  getOwnPropertyDescriptor(k) { throw "myexn" }
1259})
1260
1261
1262
1263// ---------------------------------------------------------------------------
1264// String conversion (Object.prototype.toString,
1265//                    Object.prototype.toLocaleString,
1266//                    Function.prototype.toString)
1267
1268var key
1269
1270function TestToString(handler) {
1271  var p = new Proxy({}, handler)
1272  key = ""
1273  assertEquals("[object Object]", Object.prototype.toString.call(p))
1274  assertEquals(Symbol.toStringTag, key)
1275  assertEquals("my_proxy", Object.prototype.toLocaleString.call(p))
1276  assertEquals("toString", key)
1277
1278  var f = new Proxy(function() {}, handler)
1279  key = ""
1280  assertEquals("[object Function]", Object.prototype.toString.call(f))
1281  assertEquals(Symbol.toStringTag, key)
1282  assertEquals("my_proxy", Object.prototype.toLocaleString.call(f))
1283  assertEquals("toString", key)
1284  assertThrows(function(){ Function.prototype.toString.call(f) })
1285
1286  var o = Object.create(p)
1287  key = ""
1288  assertEquals("[object Object]", Object.prototype.toString.call(o))
1289  assertEquals(Symbol.toStringTag, key)
1290  assertEquals("my_proxy", Object.prototype.toLocaleString.call(o))
1291  assertEquals("toString", key)
1292}
1293
1294TestToString({
1295  get: function(r, k) { key = k; return function() { return "my_proxy" } }
1296})
1297
1298TestToString({
1299  get: function(r, k) { return this.get2(r, k) },
1300  get2: function(r, k) { key = k; return function() { return "my_proxy" } }
1301})
1302
1303TestToString(new Proxy({}, {
1304  get: function(pr, pk) {
1305    return function(r, k) { key = k; return function() { return "my_proxy" } }
1306  }
1307}))
1308
1309
1310function TestToStringThrow(handler) {
1311  var p = new Proxy({}, handler)
1312  assertThrowsEquals(() => Object.prototype.toString.call(p), "myexn")
1313  assertThrowsEquals(() => Object.prototype.toLocaleString.call(p), "myexn")
1314
1315  var f = new Proxy(function(){}, handler)
1316  assertThrowsEquals(() => Object.prototype.toString.call(f), "myexn")
1317  assertThrowsEquals(() => Object.prototype.toLocaleString.call(f), "myexn")
1318
1319  var o = Object.create(p)
1320  assertThrowsEquals(() => Object.prototype.toString.call(o), "myexn")
1321  assertThrowsEquals(() => Object.prototype.toLocaleString.call(o), "myexn")
1322}
1323
1324TestToStringThrow({
1325  get: function(r, k) { throw "myexn" }
1326})
1327
1328TestToStringThrow({
1329  get: function(r, k) { return this.get2(r, k) },
1330  get2: function(r, k) { throw "myexn" }
1331})
1332
1333TestToStringThrow(new Proxy({}, {
1334  get: function(pr, pk) { throw "myexn" }
1335}))
1336
1337TestToStringThrow(new Proxy({}, {
1338  get: function(pr, pk) {
1339    return function(r, k) { throw "myexn" }
1340  }
1341}))
1342
1343
1344// ---------------------------------------------------------------------------
1345// Value conversion (Object.prototype.toValue)
1346
1347function TestValueOf(handler) {
1348  TestWithProxies(TestValueOf2, handler)
1349}
1350
1351function TestValueOf2(create, handler) {
1352  var p = create(handler)
1353  assertSame(p, Object.prototype.valueOf.call(p))
1354}
1355
1356TestValueOf({})
1357
1358
1359
1360// ---------------------------------------------------------------------------
1361// Enumerability (Object.prototype.propertyIsEnumerable)
1362
1363var key
1364
1365function TestIsEnumerable(handler) {
1366  TestWithProxies(TestIsEnumerable2, handler)
1367}
1368
1369function TestIsEnumerable2(create, handler) {
1370  var p = create(handler)
1371  assertTrue(Object.prototype.propertyIsEnumerable.call(p, "a"))
1372  assertEquals("a", key)
1373  assertTrue(Object.prototype.propertyIsEnumerable.call(p, 2))
1374  assertEquals("2", key)
1375  assertFalse(Object.prototype.propertyIsEnumerable.call(p, "z"))
1376  assertEquals("z", key)
1377
1378  var o = Object.create(p)
1379  key = ""
1380  assertFalse(Object.prototype.propertyIsEnumerable.call(o, "a"))
1381  assertEquals("", key)  // trap not invoked
1382}
1383
1384TestIsEnumerable({
1385  getOwnPropertyDescriptor(t, k) {
1386    key = k;
1387    return {enumerable: k < "z", configurable: true}
1388  },
1389})
1390
1391TestIsEnumerable({
1392  getOwnPropertyDescriptor: function(t, k) {
1393    return this.getOwnPropertyDescriptor2(k)
1394  },
1395  getOwnPropertyDescriptor2: function(k) {
1396    key = k;
1397    return {enumerable: k < "z", configurable: true}
1398  },
1399})
1400
1401TestIsEnumerable({
1402  getOwnPropertyDescriptor: function(t, k) {
1403    key = k;
1404    return {get enumerable() { return k < "z" }, configurable: true}
1405  },
1406})
1407
1408TestIsEnumerable(new Proxy({}, {
1409  get: function(pt, pk, pr) {
1410    return function(t, k) {
1411      key = k;
1412      return {enumerable: k < "z", configurable: true}
1413    }
1414  }
1415}))
1416
1417
1418// ---------------------------------------------------------------------------
1419function TestIsEnumerableThrow(handler) {
1420  TestWithProxies(TestIsEnumerableThrow2, handler)
1421}
1422
1423function TestIsEnumerableThrow2(create, handler) {
1424  var p = create(handler)
1425  assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, "a"),
1426      "myexn")
1427  assertThrowsEquals(() => Object.prototype.propertyIsEnumerable.call(p, 11),
1428      "myexn")
1429}
1430
1431TestIsEnumerableThrow({
1432  getOwnPropertyDescriptor: function(k) { throw "myexn" }
1433})
1434
1435TestIsEnumerableThrow({
1436  getOwnPropertyDescriptor: function(k) {
1437    return this.getOwnPropertyDescriptor2(k)
1438  },
1439  getOwnPropertyDescriptor2: function(k) { throw "myexn" }
1440})
1441
1442TestIsEnumerableThrow({
1443  getOwnPropertyDescriptor: function(k) {
1444    return {get enumerable() { throw "myexn" }, configurable: true}
1445  },
1446})
1447
1448TestIsEnumerableThrow(new Proxy({}, {
1449  get: function(pr, pk) { throw "myexn" }
1450}))
1451
1452TestIsEnumerableThrow(new Proxy({}, {
1453  get: function(pr, pk) {
1454    return function(k) { throw "myexn" }
1455  }
1456}));
1457
1458
1459
1460// ---------------------------------------------------------------------------
1461// Constructor functions with proxy prototypes.
1462
1463(function TestConstructorWithProxyPrototype() {
1464  TestWithProxies(TestConstructorWithProxyPrototype2, {})
1465})();
1466
1467function TestConstructorWithProxyPrototype2(create, handler) {
1468  function C() {};
1469  C.prototype = create(handler);
1470
1471  var o = new C;
1472  assertSame(C.prototype, Object.getPrototypeOf(o));
1473};
1474
1475
1476(function TestOptWithProxyPrototype() {
1477  var handler = {
1478    get(t, k) {
1479      return 10;
1480    }
1481  };
1482
1483  function C() {};
1484  C.prototype = new Proxy({}, handler);
1485  var o = new C();
1486
1487  function f() {
1488    return o.x;
1489  }
1490  assertEquals(10, f());
1491  assertEquals(10, f());
1492  %OptimizeFunctionOnNextCall(f);
1493  assertEquals(10, f());
1494})();
1495