OLD | NEW |
| (Empty) |
1 // Copyright 2008 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 /** | |
29 * @fileoverview Test splice, shift, unshift, slice and join on small | |
30 * and large arrays. Some of these methods are specified such that they | |
31 * should work on other objects too, so we test that too. | |
32 */ | |
33 | |
34 var LARGE = 40000000; | |
35 var VERYLARGE = 4000000000; | |
36 | |
37 // Nicer for firefox 1.5. Unless you uncomment the following two lines, | |
38 // smjs will appear to hang on this file. | |
39 //var LARGE = 40000; | |
40 //var VERYLARGE = 40000; | |
41 | |
42 var fourhundredth = LARGE/400; | |
43 | |
44 function PseudoArray() { | |
45 }; | |
46 | |
47 for (var use_real_arrays = 0; use_real_arrays <= 1; use_real_arrays++) { | |
48 var poses = [0, 140, 20000, VERYLARGE]; | |
49 var the_prototype; | |
50 var new_function; | |
51 var push_function; | |
52 var concat_function; | |
53 var slice_function; | |
54 var splice_function; | |
55 var splice_function_2; | |
56 var unshift_function; | |
57 var unshift_function_2; | |
58 var shift_function; | |
59 if (use_real_arrays) { | |
60 new_function = function(length) { | |
61 return new Array(length); | |
62 }; | |
63 the_prototype = Array.prototype; | |
64 push_function = function(array, elt) { | |
65 return array.push(elt); | |
66 }; | |
67 concat_function = function(array, other) { | |
68 return array.concat(other); | |
69 }; | |
70 slice_function = function(array, start, len) { | |
71 return array.slice(start, len); | |
72 }; | |
73 splice_function = function(array, start, len) { | |
74 return array.splice(start, len); | |
75 }; | |
76 splice_function_2 = function(array, start, len, elt) { | |
77 return array.splice(start, len, elt); | |
78 }; | |
79 unshift_function = function(array, elt) { | |
80 return array.unshift(elt); | |
81 }; | |
82 unshift_function_2 = function(array, elt1, elt2) { | |
83 return array.unshift(elt1, elt2); | |
84 }; | |
85 shift_function = function(array) { | |
86 return array.shift(); | |
87 }; | |
88 } else { | |
89 // Don't run largest size on non-arrays or we'll be here for ever. | |
90 poses.pop(); | |
91 new_function = function(length) { | |
92 var obj = new PseudoArray(); | |
93 obj.length = length; | |
94 return obj; | |
95 }; | |
96 the_prototype = PseudoArray.prototype; | |
97 push_function = function(array, elt) { | |
98 array[array.length] = elt; | |
99 array.length++; | |
100 }; | |
101 concat_function = function(array, other) { | |
102 return Array.prototype.concat.call(array, other); | |
103 }; | |
104 slice_function = function(array, start, len) { | |
105 return Array.prototype.slice.call(array, start, len); | |
106 }; | |
107 splice_function = function(array, start, len) { | |
108 return Array.prototype.splice.call(array, start, len); | |
109 }; | |
110 splice_function_2 = function(array, start, len, elt) { | |
111 return Array.prototype.splice.call(array, start, len, elt); | |
112 }; | |
113 unshift_function = function(array, elt) { | |
114 return Array.prototype.unshift.call(array, elt); | |
115 }; | |
116 unshift_function_2 = function(array, elt1, elt2) { | |
117 return Array.prototype.unshift.call(array, elt1, elt2); | |
118 }; | |
119 shift_function = function(array) { | |
120 return Array.prototype.shift.call(array); | |
121 }; | |
122 } | |
123 | |
124 for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) { | |
125 var pos = poses[pos_pos]; | |
126 if (pos > 100) { | |
127 var a = new_function(pos); | |
128 assertEquals(pos, a.length); | |
129 push_function(a, 'foo'); | |
130 assertEquals(pos + 1, a.length); | |
131 var b = ['bar']; | |
132 // Delete a huge number of holes. | |
133 var c = splice_function(a, 10, pos - 20); | |
134 assertEquals(pos - 20, c.length); | |
135 assertEquals(21, a.length); | |
136 } | |
137 | |
138 // Add a numeric property to the prototype of the array class. This | |
139 // allows us to test some borderline stuff relative to the standard. | |
140 the_prototype["" + (pos + 1)] = 'baz'; | |
141 | |
142 if (use_real_arrays) { | |
143 // It seems quite clear from ECMAScript spec 15.4.4.5. Just call Get on | |
144 // every integer in the range. | |
145 // IE, Safari get this right. | |
146 // FF, Opera get this wrong. | |
147 var a = ['zero', ,'two']; | |
148 if (pos == 0) { | |
149 assertEquals("zero,baz,two", a.join(",")); | |
150 } | |
151 | |
152 // Concat only applies to real arrays, unlike most of the other methods. | |
153 var a = new_function(pos); | |
154 push_function(a, "con"); | |
155 assertEquals("con", a[pos]); | |
156 assertEquals(pos + 1, a.length); | |
157 var b = new_function(0); | |
158 push_function(b, "cat"); | |
159 assertEquals("cat", b[0]); | |
160 var ab = concat_function(a, b); | |
161 assertEquals("con", ab[pos]); | |
162 assertEquals(pos + 2, ab.length); | |
163 assertEquals("cat", ab[pos + 1]); | |
164 var ba = concat_function(b, a); | |
165 assertEquals("con", ba[pos + 1]); | |
166 assertEquals(pos + 2, ba.length); | |
167 assertEquals("cat", ba[0]); | |
168 | |
169 // Join with '' as separator. | |
170 var join = a.join(''); | |
171 assertEquals("con", join); | |
172 join = b.join(''); | |
173 assertEquals("cat", join); | |
174 join = ab.join(''); | |
175 assertEquals("concat", join); | |
176 join = ba.join(''); | |
177 assertEquals("catcon", join); | |
178 | |
179 var sparse = []; | |
180 sparse[pos + 1000] = 'is '; | |
181 sparse[pos + 271828] = 'time '; | |
182 sparse[pos + 31415] = 'the '; | |
183 sparse[pos + 012260199] = 'all '; | |
184 sparse[-1] = 'foo'; | |
185 sparse[pos + 22591927] = 'good '; | |
186 sparse[pos + 1618033] = 'for '; | |
187 sparse[pos + 91] = ': Now '; | |
188 sparse[pos + 86720199] = 'men.'; | |
189 sparse.hest = 'fisk'; | |
190 | |
191 assertEquals("baz: Now is the time for all good men.", sparse.join('')); | |
192 } | |
193 | |
194 a = new_function(pos); | |
195 push_function(a, 'zero'); | |
196 push_function(a, void 0); | |
197 push_function(a, 'two'); | |
198 | |
199 // Splice works differently from join. | |
200 // IE, Safari get this wrong. | |
201 // FF, Opera get this right. | |
202 // 15.4.4.12 line 24 says the object itself has to have the property... | |
203 var zero = splice_function(a, pos, 1); | |
204 assertEquals("undefined", typeof(a[pos])); | |
205 assertEquals("two", a[pos+1], "pos1:" + pos); | |
206 assertEquals(pos + 2, a.length, "a length"); | |
207 assertEquals(1, zero.length, "zero length"); | |
208 assertEquals("zero", zero[0]); | |
209 | |
210 // 15.4.4.12 line 41 says the object itself has to have the property... | |
211 a = new_function(pos); | |
212 push_function(a, 'zero'); | |
213 push_function(a, void 0); | |
214 push_function(a, 'two'); | |
215 var nothing = splice_function_2(a, pos, 0, 'minus1'); | |
216 assertEquals("minus1", a[pos]); | |
217 assertEquals("zero", a[pos+1]); | |
218 assertEquals("undefined", typeof(a[pos+2]), "toot!"); | |
219 assertEquals("two", a[pos+3], "pos3"); | |
220 assertEquals(pos + 4, a.length); | |
221 assertEquals(1, zero.length); | |
222 assertEquals("zero", zero[0]); | |
223 | |
224 // 15.4.4.12 line 10 says the object itself has to have the property... | |
225 a = new_function(pos); | |
226 push_function(a, 'zero'); | |
227 push_function(a, void 0); | |
228 push_function(a, 'two'); | |
229 var one = splice_function(a, pos + 1, 1); | |
230 assertEquals("", one.join(",")); | |
231 assertEquals(pos + 2, a.length); | |
232 assertEquals("zero", a[pos]); | |
233 assertEquals("two", a[pos+1]); | |
234 | |
235 // Set things back to the way they were. | |
236 the_prototype[pos + 1] = undefined; | |
237 | |
238 // Unshift. | |
239 var a = new_function(pos); | |
240 push_function(a, "foo"); | |
241 assertEquals("foo", a[pos]); | |
242 assertEquals(pos + 1, a.length); | |
243 unshift_function(a, "bar"); | |
244 assertEquals("foo", a[pos+1]); | |
245 assertEquals(pos + 2, a.length); | |
246 assertEquals("bar", a[0]); | |
247 unshift_function_2(a, "baz", "boo"); | |
248 assertEquals("foo", a[pos+3]); | |
249 assertEquals(pos + 4, a.length); | |
250 assertEquals("baz", a[0]); | |
251 assertEquals("boo", a[1]); | |
252 assertEquals("bar", a[2]); | |
253 | |
254 // Shift. | |
255 var baz = shift_function(a); | |
256 assertEquals("baz", baz); | |
257 assertEquals("boo", a[0]); | |
258 assertEquals(pos + 3, a.length); | |
259 assertEquals("foo", a[pos + 2]); | |
260 | |
261 // Slice. | |
262 var bar = slice_function(a, 1, 0); // don't throw an exception please. | |
263 bar = slice_function(a, 1, 2); | |
264 assertEquals("bar", bar[0]); | |
265 assertEquals(1, bar.length); | |
266 assertEquals("bar", a[1]); | |
267 | |
268 } | |
269 } | |
270 | |
271 // Lets see if performance is reasonable. | |
272 | |
273 var a = new Array(LARGE + 10); | |
274 for (var i = 0; i < a.length; i += 1000) { | |
275 a[i] = i; | |
276 } | |
277 | |
278 // Take something near the end of the array. | |
279 for (var i = 0; i < 100; i++) { | |
280 var top = a.splice(LARGE, 5); | |
281 assertEquals(5, top.length); | |
282 assertEquals(LARGE, top[0]); | |
283 assertEquals("undefined", typeof(top[1])); | |
284 assertEquals(LARGE + 5, a.length); | |
285 a.splice(LARGE, 0, LARGE); | |
286 a.length = LARGE + 10; | |
287 } | |
288 | |
289 var a = new Array(LARGE + 10); | |
290 for (var i = 0; i < a.length; i += fourhundredth) { | |
291 a[i] = i; | |
292 } | |
293 | |
294 // Take something near the middle of the array. | |
295 for (var i = 0; i < 10; i++) { | |
296 var top = a.splice(LARGE >> 1, 5); | |
297 assertEquals(5, top.length); | |
298 assertEquals(LARGE >> 1, top[0]); | |
299 assertEquals("undefined", typeof(top[1])); | |
300 assertEquals(LARGE + 5, a.length); | |
301 a.splice(LARGE >> 1, 0, LARGE >> 1, void 0, void 0, void 0, void 0); | |
302 } | |
303 | |
304 | |
305 // Test http://b/issue?id=1202711 | |
306 arr = [0]; | |
307 arr.length = 2; | |
308 Array.prototype[1] = 1; | |
309 assertEquals(1, arr.pop()); | |
310 assertEquals(0, arr.pop()); | |
311 Array.prototype[1] = undefined; | |
312 | |
313 // Test http://code.google.com/p/chromium/issues/detail?id=21860 | |
314 Array.prototype.push.apply([], [1].splice(0, -(-1 % 5))); | |
OLD | NEW |