JSTests:
[WebKit-https.git] / JSTests / stress / proxy-own-keys.js
1 function assert(b) {
2     if (!b)
3         throw new Error("Bad assertion");
4 }
5
6 {
7     let error = null;
8     let target = { };
9     let handler = {
10         ownKeys: function() {
11             error = new Error;
12             throw error;
13         }
14     };
15
16     let proxy = new Proxy(target, handler);
17     for (let i = 0; i < 500; i++) {
18         let threw = false;
19         try {
20             Object.keys(proxy);
21         } catch(e) {
22             threw = true;
23             assert(e === error);
24         }
25         assert(threw);
26     }
27 }
28
29 {
30     let error = null;
31     let target = { };
32     let handler = {
33         get ownKeys() {
34             error = new Error;
35             throw error;
36         }
37     };
38
39     let proxy = new Proxy(target, handler);
40     for (let i = 0; i < 500; i++) {
41         let threw = false;
42         try {
43             Object.keys(proxy);
44         } catch(e) {
45             threw = true;
46             assert(e === error);
47         }
48         assert(threw);
49     }
50 }
51
52 {
53     let target = {
54         x: 40
55     };
56     let called = false;
57     let handler = {
58         ownKeys: function(theTarget) {
59             called = true;
60             return ["1", 2, 3];
61         }
62     };
63
64     let proxy = new Proxy(target, handler);
65     for (let i = 0; i < 500; i++) {
66         let threw = false;
67         try {
68             Object.keys(proxy);
69         } catch(e) {
70             threw = true;
71             assert(e.toString() === "TypeError: Proxy handler's 'ownKeys' method must return an array-like object containing only Strings and Symbols");
72         }
73         assert(threw);
74         assert(called);
75         called = false;
76     }
77 }
78
79 {
80     let target = { };
81     Object.defineProperty(target, "x", {
82         configurable: false,
83         enumerable: true,
84         value: 400
85     });
86     let called = false;
87     let handler = {
88         ownKeys: function(theTarget) {
89             called = true;
90             return [];
91         }
92     };
93
94     let proxy = new Proxy(target, handler);
95     for (let i = 0; i < 500; i++) {
96         let threw = false;
97         try {
98             Object.keys(proxy);
99         } catch(e) {
100             threw = true;
101             assert(e.toString() === "TypeError: Proxy object's 'target' has the non-configurable property 'x' that was not in the result from the 'ownKeys' trap");
102         }
103         assert(threw);
104         assert(called);
105         called = false;
106     }
107 }
108
109 {
110     let target = { };
111     Object.defineProperty(target, "x", {
112         configurable: true,
113         enumerable: true,
114         value: 400
115     });
116     Object.preventExtensions(target);
117     let called = false;
118     let handler = {
119         ownKeys: function(theTarget) {
120             called = true;
121             return [];
122         }
123     };
124
125     let proxy = new Proxy(target, handler);
126     for (let i = 0; i < 500; i++) {
127         let threw = false;
128         try {
129             Object.keys(proxy);
130         } catch(e) {
131             threw = true;
132             assert(e.toString() === "TypeError: Proxy object's non-extensible 'target' has configurable property 'x' that was not in the result from the 'ownKeys' trap");
133         }
134         assert(threw);
135         assert(called);
136         called = false;
137     }
138 }
139
140 {
141     let target = { };
142     Object.defineProperty(target, "x", {
143         configurable: true,
144         enumerable: true,
145         value: 400
146     });
147     Object.preventExtensions(target);
148     let called = false;
149     let handler = {
150         ownKeys: function(theTarget) {
151             called = true;
152             return ["x", "y"];
153         }
154     };
155
156     let proxy = new Proxy(target, handler);
157     for (let i = 0; i < 500; i++) {
158         let threw = false;
159         try {
160             Object.keys(proxy);
161         } catch(e) {
162             threw = true;
163             assert(e.toString() === "TypeError: Proxy handler's 'ownKeys' method returned a key that was not present in its non-extensible target");
164         }
165         assert(threw);
166         assert(called);
167         called = false;
168     }
169 }
170
171 {
172     let target = {};
173     let called1 = false;
174     let called2 = false;
175     Object.defineProperty(target, 'a', { value: 42, configurable: false });
176     let p1 = new Proxy(target, {
177         ownKeys() {
178             called1 = true;
179             return ['a', 'a'];
180         }
181     });
182     let p2 = new Proxy(p1, {
183         ownKeys() {
184             called2 = true;
185             return ['a'];
186         }
187     });
188
189     for (let i = 0; i < 500; i++) {
190         // Throws per https://github.com/tc39/ecma262/pull/833
191         let threw = false;
192         try {
193             Reflect.ownKeys(p2);
194         } catch(e) {
195             assert(e.toString() === "TypeError: Proxy handler's 'ownKeys' trap result must not contain any duplicate names");
196             threw = true;
197         }
198         assert(threw);
199         assert(called1);
200         assert(called2);
201     }
202 }
203
204 {
205     let target = {};
206     let called1 = false;
207     let called2 = false;
208     Object.defineProperty(target, 'a', { value: 42, configurable: true });
209     Object.preventExtensions(target);
210     let p1 = new Proxy(target, {
211         ownKeys() {
212             called1 = true;
213             return ['a', 'a'];
214         }
215     });
216     let p2 = new Proxy(p1, {
217         ownKeys() {
218             called2 = true;
219             return ['a'];
220         }
221     });
222
223     for (let i = 0; i < 500; i++) {
224         // Throws per https://github.com/tc39/ecma262/pull/833
225         let threw = false;
226         try {
227             Reflect.ownKeys(p2);
228         } catch(e) {
229             assert(e.toString() === "TypeError: Proxy handler's 'ownKeys' trap result must not contain any duplicate names");
230             threw = true;
231         }
232         assert(threw);
233         assert(called1);
234         assert(called2);
235     }
236 }
237
238 {
239     let target = { };
240     Object.defineProperty(target, "x", {
241         configurable: true,
242         enumerable: true,
243         value: 400
244     });
245     Object.preventExtensions(target);
246     let called = false;
247     let handler = {
248         ownKeys: function(theTarget) {
249             called = true;
250             return ["x", "x"];
251         }
252     };
253
254     let proxy = new Proxy(target, handler);
255     for (let i = 0; i < 500; i++) {
256         try {
257             Object.keys(proxy);
258         } catch(e) {
259             assert(e.toString() === "TypeError: Proxy handler's 'ownKeys' trap result must not contain any duplicate names");
260             threw = true;
261         }
262         assert(called);
263         assert(threw);
264         called = false;
265         threw = false;
266     }
267 }
268
269 {
270     let target = { };
271     let handler = {
272         ownKeys: 45
273     };
274
275     let proxy = new Proxy(target, handler);
276     for (let i = 0; i < 500; i++) {
277         let threw = false;
278         try {
279             Object.keys(proxy);
280         } catch(e) {
281             threw = true;
282             assert(e.toString() === "TypeError: 'ownKeys' property of a Proxy's handler should be callable");
283         }
284         assert(threw);
285     }
286 }
287
288 function shallowEq(a, b) {
289     if (a.length !== b.length)
290         return false;
291     for (let i = 0; i < a.length; i++) {
292         if (a[i] !== b[i])
293             return false;
294     }
295
296     return true;
297 }
298
299 {
300     let target = {
301         x: 40
302     };
303     let called = false;
304     let arr = ["a", "b", "c"];
305     let handler = {
306         ownKeys: function(theTarget) {
307             called = true;
308             return arr;
309         }
310     };
311
312     let proxy = new Proxy(target, handler);
313     for (let i = 0; i < 500; i++) {
314         let result = Object.keys(proxy);
315         assert(result !== arr);
316         assert(shallowEq(result, []));
317         assert(called);
318         called = false;
319     }
320 }
321
322 {
323     let target = {
324         x: 40
325     };
326     let called = false;
327     let arr = ["a", "b", "c"];
328     let handler = {
329         getOwnPropertyDescriptor: function(theTarget, propertyName) {
330             if (arr.indexOf(propertyName) >= 0) {
331                 return {
332                     enumerable: true,
333                     configurable: true
334                 };
335             }
336             return Reflect.getOwnPropertyDescriptor(theTarget, propertyName);
337         },
338
339         ownKeys: function(theTarget) {
340             called = true;
341             return arr;
342         }
343     };
344
345     let proxy = new Proxy(target, handler);
346     for (let i = 0; i < 500; i++) {
347         let result = Object.keys(proxy);
348         assert(result !== arr);
349         assert(shallowEq(result, arr));
350         assert(called);
351         called = false;
352     }
353 }
354
355 {
356     let target = {
357         x: 40
358     };
359     let called = false;
360     let arr = ["a", "b", "c"];
361     let handler = {
362         ownKeys: function(theTarget) {
363             called = true;
364             return arr;
365         }
366     };
367
368     let proxy = new Proxy(target, handler);
369     for (let i = 0; i < 500; i++) {
370         let result = Reflect.ownKeys(proxy);
371         assert(result !== arr);
372         assert(shallowEq(result, arr));
373         assert(called);
374         called = false;
375     }
376 }
377
378 {
379     let target = {
380         x: 40
381     };
382     let called = false;
383     let s1 = Symbol();
384     let s2 = Symbol();
385     let arr = ["a", "b", s1, "c", s2];
386     let handler = {
387         ownKeys: function(theTarget) {
388             called = true;
389             return arr;
390         }
391     };
392
393     let proxy = new Proxy(target, handler);
394     for (let i = 0; i < 500; i++) {
395         let result = Object.getOwnPropertySymbols(proxy);
396         assert(shallowEq(result, [s1, s2]));
397         assert(called);
398         called = false;
399     }
400 }
401
402 {
403     let target = {
404         x: 40
405     };
406     let called = false;
407     let s1 = Symbol();
408     let s2 = Symbol();
409     let arr = ["a", "b", s1, "c", s2];
410     let handler = {
411         getOwnPropertyDescriptor(theTarget, propertyName) {
412             if (arr.indexOf(propertyName) >= 0) {
413                 return {
414                     enumerable: true,
415                     configurable: true
416                 }
417             }
418             return Reflect.getOwnPropertyDescriptor(theTarget, propertyName);
419         },
420         ownKeys: function(theTarget) {
421             called = true;
422             return arr;
423         }
424     };
425
426     let proxy = new Proxy(target, handler);
427     for (let i = 0; i < 500; i++) {
428         let result = Object.keys(proxy);
429         assert(shallowEq(result, ["a", "b", "c"]));
430         assert(called);
431         called = false;
432     }
433 }
434
435 {
436     let target = {
437         x: 40
438     };
439     let called = false;
440     let s1 = Symbol();
441     let s2 = Symbol();
442     let arr = ["a", "b", s1, "c", s2];
443     let handler = {
444         ownKeys: function(theTarget) {
445             called = true;
446             return arr;
447         }
448     };
449
450     let proxy = new Proxy(target, handler);
451     for (let i = 0; i < 500; i++) {
452         let result = Reflect.ownKeys(proxy);
453         assert(shallowEq(result, ["a", "b", "c", s1, s2]));
454         assert(called);
455         called = false;
456     }
457 }
458
459 {
460     let target = {
461         x: 40
462     };
463     let called = false;
464     let s1 = Symbol();
465     let s2 = Symbol();
466     let arr = ["a", "b", s1, "c", s2];
467     let handler = {
468         getOwnPropertyDescriptor: () => {
469             return { enumerable: true, configurable: true }
470         },
471         ownKeys: function(theTarget) {
472             called = true;
473             return arr;
474         }
475     };
476
477     let proxy = new Proxy(target, handler);
478     for (let i = 0; i < 500; i++) {
479         let set = new Set;
480         for (let p in proxy)
481             set.add(p);
482         assert(set.size === 3);
483         assert(set.has("a"));
484         assert(set.has("b"));
485         assert(set.has("c"));
486         assert(called);
487         called = false;
488     }
489 }
490
491 {
492     let target = {
493         x: 40
494     };
495     let called = false;
496     let s1 = Symbol();
497     let s2 = Symbol();
498     let arr = ["a", "b", s1, "c", s2];
499     let handler = {
500         getOwnPropertyDescriptor: () => {
501             return { enumerable: true, configurable: true }
502         },
503         ownKeys: function(theTarget) {
504             called = true;
505             return arr;
506         }
507     };
508
509     let proxy = new Proxy(target, handler);
510     for (let i = 0; i < 500; i++) {
511         let set = new Set;
512         for (let p in proxy)
513             set.add(p);
514         if (i === 40) { // Make sure we don't cache the result.
515             arr.push("d");
516         }
517         assert(set.size === i > 40 ? 4 : 3);
518         assert(set.has("a"));
519         assert(set.has("b"));
520         assert(set.has("c"));
521         if (i > 40)
522             assert(set.has("d"));
523         assert(called);
524         called = false;
525     }
526 }
527
528 {
529     let target = {
530         x: 40
531     };
532     let called = false;
533     let s1 = Symbol();
534     let s2 = Symbol();
535     let arr = ["a", "b", s1, "c", s2];
536     let handler = {
537         getOwnPropertyDescriptor: () => {
538             return { enumerable: true, configurable: true }
539         },
540         ownKeys: function(theTarget) {
541             called = true;
542             return arr;
543         }
544     };
545
546     let proxy = new Proxy(target, handler);
547     let proxyish = Object.create(proxy, {
548         d: { enumerable: true, configurable: true }
549     });
550     for (let i = 0; i < 500; i++) {
551         let set = new Set;
552         for (let p in proxyish)
553             set.add(p);
554         assert(set.size === 4);
555         assert(set.has("a"));
556         assert(set.has("b"));
557         assert(set.has("c"));
558         assert(set.has("d"));
559         assert(called);
560         called = false;
561     }
562 }
563
564 {
565     let target = {
566         x: 40
567     };
568     let called = false;
569     let s1 = Symbol();
570     let s2 = Symbol();
571     let arr = ["a", "b", s1, "c", s2];
572     let handler = {
573         getOwnPropertyDescriptor: () => {
574             return { enumerable: true, configurable: true }
575         },
576         ownKeys: function(theTarget) {
577             called = true;
578             return arr;
579         }
580     };
581
582     let proxy = new Proxy(target, handler);
583     let proxyish = Object.create(proxy, {
584         d: { enumerable: true, configurable: true }
585     });
586     for (let i = 0; i < 500; i++) {
587         let set = new Set;
588         for (let p in proxyish)
589             set.add(p);
590         assert(set.size === 4);
591         assert(set.has("a"));
592         assert(set.has("b"));
593         assert(set.has("c"));
594         assert(set.has("d"));
595         assert(called);
596         called = false;
597     }
598 }
599
600 {
601     let called = false;
602     let target = {x: 20, y: 40};
603     let handler = {
604         ownKeys: null
605     };
606
607     let proxy = new Proxy(target, handler);
608     for (let i = 0; i < 500; i++) {
609         let keys = Object.keys(proxy);
610         assert(keys.indexOf("x") !== -1);
611         assert(keys.indexOf("y") !== -1);
612     }
613 }
614
615 {
616     let called = false;
617     let target = new Proxy({}, {
618         ownKeys: function(theTarget) {
619             called = true;
620             return Reflect.ownKeys(theTarget);
621         }
622     });
623     let s1 = Symbol();
624     let s2 = Symbol();
625     let arr = ["a", "b", s1, "c", s2];
626     let handler = {
627         ownKeys: function(theTarget) {
628             return arr;
629         }
630     };
631
632     let proxy = new Proxy(target, handler);
633     for (let i = 0; i < 500; i++) {
634         let keys = Object.keys(proxy);
635         assert(called);
636         called = false;
637     }
638 }
639
640 {
641     let error = null;
642     let target = new Proxy({}, {
643         ownKeys: function(theTarget) {
644             error = new Error;
645             throw error;
646         }
647     });
648     let s1 = Symbol();
649     let s2 = Symbol();
650     let arr = ["a", "b", s1, "c", s2];
651     let handler = {
652         ownKeys: function(theTarget) {
653             return arr;
654         }
655     };
656
657     let proxy = new Proxy(target, handler);
658     for (let i = 0; i < 500; i++) {
659         let threw = false;
660         try {
661             Object.keys(proxy);
662         } catch(e) {
663             threw = true;
664             assert(e === error);
665         }
666         assert(threw);
667         error = null;
668     }
669 }