Speculatively change iteration protocall to use the same next function
[WebKit-https.git] / JSTests / stress / spread-optimized-properly.js
1 function assert(b) {
2     if (!b)
3         throw new Error("Bad assertion");
4 }
5
6 function test(f) { f(); }
7
8 function shallowEq(a, b) {
9     if (a.length !== b.length)
10         return false;
11     for (let i = 0; i < a.length; ++i) {
12         if (a[i] !== b[i])
13             return false;
14     }
15     return true;
16 }
17
18 function makeArrayIterator(arr, f) {
19     let i = 0;
20     return {
21         next() {
22             f();
23             if (i >= arr.length)
24                 return {done: true};
25             return {value: arr[i++], done: false};
26         }
27     };
28
29
30 test(function() {
31     let arr = [10, 20];
32     arr.__proto__ = {[Symbol.iterator]: Array.prototype[Symbol.iterator]};
33     function bar(a) {
34         a.x;
35         return [...a];
36     }
37     noInline(bar);
38     for (let i = 0; i < 10000; i++) {
39         assert(shallowEq(bar(arr), arr));
40     }
41 });
42
43 test(function() {
44     let arr = [10, 20];
45     let count = 0;
46     function callback() {
47         count++;
48     }
49
50     arr.__proto__ = {
51         [Symbol.iterator]: function() {
52             return makeArrayIterator(this, callback);
53         }
54     };
55
56     function bar(a) {
57         a.x;
58         return [...a];
59     }
60     noInline(bar);
61     for (let i = 0; i < 10000; i++) {
62         let t = bar(arr);
63         assert(count === 3);
64         count = 0;
65         assert(shallowEq(t, arr));
66     }
67 });
68
69 test(function() {
70     let arr = [10, 20];
71     let count = 0;
72     function callback() {
73         count++;
74     }
75
76     arr[Symbol.iterator] = function() {
77         return makeArrayIterator(this, callback);
78     };
79
80     function bar(a) {
81         a.x;
82         return [...a];
83     }
84     noInline(bar);
85     for (let i = 0; i < 10000; i++) {
86         let t = bar(arr);
87         assert(count === 3);
88         count = 0;
89         assert(shallowEq(t, arr));
90     }
91 });
92
93 test(function() {
94     let arr = [10, 20];
95     arr[Symbol.iterator] = Array.prototype[Symbol.iterator];
96     function bar(a) {
97         a.x;
98         return [...a];
99     }
100     noInline(bar);
101     for (let i = 0; i < 10000; i++) {
102         assert(shallowEq(bar(arr), arr));
103     }
104 });
105
106 test(function() {
107     let arr = [, 20];
108     let callCount = 0;
109     Object.defineProperty(arr, 0, {get() { ++callCount; return 10; }});
110     function bar(a) {
111         a.x;
112         return [...a];
113     }
114     noInline(bar);
115     for (let i = 0; i < 10000; i++) {
116         let t = bar(arr);
117         assert(callCount === 1);
118         assert(shallowEq(t, arr));
119         assert(callCount === 2);
120         callCount = 0;
121     }
122 });
123
124 // We run this test last since it fires watchpoints for the protocol.
125 test(function() {
126     let iter = [][Symbol.iterator]();
127     let iterProto = Object.getPrototypeOf(iter);
128     let oldNext = iterProto.next;
129
130     function hackedNext() {
131         let val = oldNext.call(this);
132         if ("value" in val) {
133             val.value++;
134         }
135         return val;
136     }
137
138     function test(a) {
139         a.x;
140         return [...a];
141     }
142
143     for (let i = 0; i < 10000; ++i) {
144         let arr = [1,,3];
145         let callCount = 0;
146         Object.defineProperty(arr, 1, { get: function() { ++callCount; iterProto.next = hackedNext; return 2; } });
147         let t = test(arr);
148         assert(callCount === 1);
149         assert(t.length === 3);
150         assert(t[0] === 1);
151         assert(t[1] === 2);
152         assert(t[2] === 3);
153         iterProto.next = oldNext;
154     }
155 });