OLD | NEW |
| (Empty) |
1 // Copyright 2017 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Flags: --type-profile | |
6 | |
7 // Add mjsunit/array-splice.js as integration test for type profile. | |
8 const expression = ` | |
9 function assertEquals() { | |
10 } | |
11 function assertFalse() { | |
12 } | |
13 function assertTrue() { | |
14 } | |
15 | |
16 // Check that splicing array of holes keeps it as array of holes | |
17 (function() { | |
18 for (var i = 0; i < 7; i++) { | |
19 var array = new Array(10); | |
20 var spliced = array.splice(1, 1, 'one', 'two'); | |
21 assertEquals(1, spliced.length); | |
22 assertFalse(0 in spliced, "0 in spliced"); | |
23 | |
24 assertEquals(11, array.length); | |
25 assertFalse(0 in array, "0 in array"); | |
26 assertTrue(1 in array); | |
27 assertTrue(2 in array); | |
28 assertFalse(3 in array, "3 in array"); | |
29 } | |
30 })(); | |
31 | |
32 | |
33 // Check various variants of empty array's splicing. | |
34 (function() { | |
35 for (var i = 0; i < 7; i++) { | |
36 assertEquals([], [].splice(0, 0)); | |
37 assertEquals([], [].splice(1, 0)); | |
38 assertEquals([], [].splice(0, 1)); | |
39 assertEquals([], [].splice(-1, 0)); | |
40 } | |
41 })(); | |
42 | |
43 | |
44 // Check that even if result array is empty, receiver gets sliced. | |
45 (function() { | |
46 for (var i = 0; i < 7; i++) { | |
47 var a = [1, 2, 3]; | |
48 assertEquals([], a.splice(1, 0, 'a', 'b', 'c')); | |
49 assertEquals([1, 'a', 'b', 'c', 2, 3], a); | |
50 } | |
51 })(); | |
52 | |
53 | |
54 // Check various forms of arguments omission. | |
55 (function() { | |
56 var array; | |
57 for (var i = 0; i < 7; i++) { | |
58 array = [1, 2, 3] | |
59 assertEquals([], array.splice()); | |
60 assertEquals([1, 2, 3], array); | |
61 | |
62 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is | |
63 // given differently from when an undefined delete count is given. | |
64 // This does not follow ECMA-262, but we do the same for | |
65 // compatibility. | |
66 array = [1, 2, 3] | |
67 assertEquals([1, 2, 3], array.splice(0)); | |
68 assertEquals([], array); | |
69 | |
70 array = [1, 2, 3] | |
71 assertEquals([1, 2, 3], array.splice(undefined)); | |
72 assertEquals([], array); | |
73 | |
74 array = [1, 2, 3] | |
75 assertEquals([1, 2, 3], array.splice("foobar")); | |
76 assertEquals([], array); | |
77 | |
78 array = [1, 2, 3] | |
79 assertEquals([], array.splice(undefined, undefined)); | |
80 assertEquals([1, 2, 3], array); | |
81 | |
82 array = [1, 2, 3] | |
83 assertEquals([], array.splice("foobar", undefined)); | |
84 assertEquals([1, 2, 3], array); | |
85 | |
86 array = [1, 2, 3] | |
87 assertEquals([], array.splice(undefined, "foobar")); | |
88 assertEquals([1, 2, 3], array); | |
89 | |
90 array = [1, 2, 3] | |
91 assertEquals([], array.splice("foobar", "foobar")); | |
92 assertEquals([1, 2, 3], array); | |
93 } | |
94 })(); | |
95 | |
96 | |
97 // Check variants of negatives and positive indices. | |
98 (function() { | |
99 var array, spliced; | |
100 for (var i = 0; i < 7; i++) { | |
101 array = [1, 2, 3, 4, 5, 6, 7]; | |
102 spliced = array.splice(-100); | |
103 assertEquals([], array); | |
104 assertEquals([1, 2, 3, 4, 5, 6, 7], spliced); | |
105 | |
106 array = [1, 2, 3, 4, 5, 6, 7]; | |
107 spliced = array.splice(-1e100); | |
108 assertEquals([], array); | |
109 assertEquals([1, 2, 3, 4, 5, 6, 7], spliced); | |
110 | |
111 array = [1, 2, 3, 4, 5, 6, 7]; | |
112 spliced = array.splice(-3); | |
113 assertEquals([1, 2, 3, 4], array); | |
114 assertEquals([5, 6, 7], spliced); | |
115 | |
116 array = [1, 2, 3, 4, 5, 6, 7]; | |
117 spliced = array.splice(-3.999999); | |
118 assertEquals([1, 2, 3, 4], array); | |
119 assertEquals([5, 6, 7], spliced); | |
120 | |
121 array = [1, 2, 3, 4, 5, 6, 7]; | |
122 spliced = array.splice(-3.000001); | |
123 assertEquals([1, 2, 3, 4], array); | |
124 assertEquals([5, 6, 7], spliced); | |
125 | |
126 array = [1, 2, 3, 4, 5, 6, 7]; | |
127 spliced = array.splice(4); | |
128 assertEquals([1, 2, 3, 4], array); | |
129 assertEquals([5, 6, 7], spliced); | |
130 | |
131 array = [1, 2, 3, 4, 5, 6, 7]; | |
132 spliced = array.splice(4.999999); | |
133 assertEquals([1, 2, 3, 4], array); | |
134 assertEquals([5, 6, 7], spliced); | |
135 | |
136 array = [1, 2, 3, 4, 5, 6, 7]; | |
137 spliced = array.splice(4.000001); | |
138 assertEquals([1, 2, 3, 4], array); | |
139 assertEquals([5, 6, 7], spliced); | |
140 | |
141 array = [1, 2, 3, 4, 5, 6, 7]; | |
142 spliced = array.splice(6); | |
143 assertEquals([1, 2, 3, 4, 5, 6], array); | |
144 assertEquals([7], spliced); | |
145 | |
146 array = [1, 2, 3, 4, 5, 6, 7]; | |
147 spliced = array.splice(7); | |
148 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
149 assertEquals([], spliced); | |
150 | |
151 array = [1, 2, 3, 4, 5, 6, 7]; | |
152 spliced = array.splice(8); | |
153 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
154 assertEquals([], spliced); | |
155 | |
156 array = [1, 2, 3, 4, 5, 6, 7]; | |
157 spliced = array.splice(100); | |
158 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
159 assertEquals([], spliced); | |
160 | |
161 array = [1, 2, 3, 4, 5, 6, 7]; | |
162 spliced = array.splice(1e100); | |
163 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
164 assertEquals([], spliced); | |
165 | |
166 array = [1, 2, 3, 4, 5, 6, 7]; | |
167 spliced = array.splice(0, -100); | |
168 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
169 assertEquals([], spliced); | |
170 | |
171 array = [1, 2, 3, 4, 5, 6, 7]; | |
172 spliced = array.splice(0, -1e100); | |
173 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
174 assertEquals([], spliced); | |
175 | |
176 array = [1, 2, 3, 4, 5, 6, 7]; | |
177 spliced = array.splice(0, -3); | |
178 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
179 assertEquals([], spliced); | |
180 | |
181 array = [1, 2, 3, 4, 5, 6, 7]; | |
182 spliced = array.splice(0, -3.999999); | |
183 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
184 assertEquals([], spliced); | |
185 | |
186 array = [1, 2, 3, 4, 5, 6, 7]; | |
187 spliced = array.splice(0, -3.000001); | |
188 assertEquals([1, 2, 3, 4, 5, 6, 7], array); | |
189 assertEquals([], spliced); | |
190 | |
191 array = [1, 2, 3, 4, 5, 6, 7]; | |
192 spliced = array.splice(0, 4); | |
193 assertEquals([5, 6, 7], array); | |
194 assertEquals([1, 2, 3, 4], spliced); | |
195 | |
196 array = [1, 2, 3, 4, 5, 6, 7]; | |
197 spliced = array.splice(0, 4.999999); | |
198 assertEquals([5, 6, 7], array); | |
199 assertEquals([1, 2, 3, 4], spliced); | |
200 | |
201 array = [1, 2, 3, 4, 5, 6, 7]; | |
202 spliced = array.splice(0, 4.000001); | |
203 assertEquals([5, 6, 7], array); | |
204 assertEquals([1, 2, 3, 4], spliced); | |
205 | |
206 array = [1, 2, 3, 4, 5, 6, 7]; | |
207 spliced = array.splice(0, 6); | |
208 assertEquals([7], array); | |
209 assertEquals([1, 2, 3, 4, 5, 6], spliced); | |
210 | |
211 array = [1, 2, 3, 4, 5, 6, 7]; | |
212 spliced = array.splice(0, 7); | |
213 assertEquals([], array); | |
214 assertEquals([1, 2, 3, 4, 5, 6, 7], spliced); | |
215 | |
216 array = [1, 2, 3, 4, 5, 6, 7]; | |
217 spliced = array.splice(0, 8); | |
218 assertEquals([], array); | |
219 assertEquals([1, 2, 3, 4, 5, 6, 7], spliced); | |
220 | |
221 array = [1, 2, 3, 4, 5, 6, 7]; | |
222 spliced = array.splice(0, 100); | |
223 assertEquals([], array); | |
224 assertEquals([1, 2, 3, 4, 5, 6, 7], spliced); | |
225 | |
226 array = [1, 2, 3, 4, 5, 6, 7]; | |
227 spliced = array.splice(0, 1e100); | |
228 assertEquals([], array); | |
229 assertEquals([1, 2, 3, 4, 5, 6, 7], spliced); | |
230 | |
231 // Some exotic cases. | |
232 obj = { toString: function() { throw 'Exception'; } }; | |
233 | |
234 // Throwing an exception in conversion: | |
235 try { | |
236 [1, 2, 3].splice(obj, 3); | |
237 throw 'Should have thrown'; | |
238 } catch (e) { | |
239 assertEquals('Exception', e); | |
240 } | |
241 | |
242 try { | |
243 [1, 2, 3].splice(0, obj, 3); | |
244 throw 'Should have thrown'; | |
245 } catch (e) { | |
246 assertEquals('Exception', e); | |
247 } | |
248 | |
249 array = [1, 2, 3]; | |
250 array.splice(0, 3, obj); | |
251 assertEquals(1, array.length); | |
252 | |
253 // Custom conversion: | |
254 array = [1, 2, 3]; | |
255 spliced = array.splice({valueOf: function() { return 1; }}, | |
256 {toString: function() { return 2; }}, | |
257 'one', 'two'); | |
258 assertEquals([2, 3], spliced); | |
259 assertEquals([1, 'one', 'two'], array); | |
260 } | |
261 })(); | |
262 | |
263 | |
264 // Nasty: modify the array in ToInteger. | |
265 (function() { | |
266 var array = []; | |
267 var spliced; | |
268 | |
269 for (var i = 0; i < 13; i++) { | |
270 bad_start = { valueOf: function() { array.push(2*i); return -1; } }; | |
271 bad_count = { valueOf: function() { array.push(2*i + 1); return 1; } }; | |
272 spliced = array.splice(bad_start, bad_count); | |
273 // According to the spec (15.4.4.12), length is calculated before | |
274 // performing ToInteger on arguments. However, v8 ignores elements | |
275 // we add while converting, so we need corrective pushes. | |
276 array.push(2*i); array.push(2*i + 1); | |
277 if (i == 0) { | |
278 assertEquals([], spliced); // Length was 0, nothing to get. | |
279 assertEquals([0, 1], array); | |
280 } else { | |
281 // When we start splice, array is [0 .. 2*i - 1], so we get | |
282 // as a result [2*i], this element is removed from the array, | |
283 // but [2 * i, 2 * i + 1] are added. | |
284 assertEquals([2 * i - 1], spliced); | |
285 assertEquals(2 * i, array[i]); | |
286 assertEquals(2 * i + 1, array[i + 1]); | |
287 } | |
288 } | |
289 })(); | |
290 | |
291 // Check the behaviour when approaching maximal values for length. | |
292 (function() { | |
293 for (var i = 0; i < 7; i++) { | |
294 try { | |
295 new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5); | |
296 throw 'Should have thrown RangeError'; | |
297 } catch (e) { | |
298 assertTrue(e instanceof RangeError); | |
299 } | |
300 | |
301 // Check smi boundary | |
302 var bigNum = (1 << 30) - 3; | |
303 var array = new Array(bigNum); | |
304 array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7); | |
305 assertEquals(bigNum + 7, array.length); | |
306 } | |
307 })(); | |
308 | |
309 (function() { | |
310 for (var i = 0; i < 7; i++) { | |
311 var a = [7, 8, 9]; | |
312 a.splice(0, 0, 1, 2, 3, 4, 5, 6); | |
313 assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a); | |
314 assertFalse(a.hasOwnProperty(10), "a.hasOwnProperty(10)"); | |
315 assertEquals(undefined, a[10]); | |
316 } | |
317 })(); | |
318 | |
319 (function testSpliceDeleteDouble() { | |
320 var a = [1.1, 1.2, 1.3, 1.4]; | |
321 a.splice(2, 1) | |
322 assertEquals([1.1, 1.2, 1.4], a); | |
323 })(); | |
324 | |
325 // Past this point the ArrayProtector is invalidated since we modify the | |
326 // Array.prototype. | |
327 | |
328 // Check the case of JS builtin .splice() | |
329 (function() { | |
330 for (var i = 0; i < 7; i++) { | |
331 var array = [1, 2, 3, 4]; | |
332 Array.prototype[3] = 'foo'; // To force JS builtin. | |
333 | |
334 var spliced = array.splice(); | |
335 | |
336 assertEquals([], spliced); | |
337 assertEquals([1, 2, 3, 4], array); | |
338 } | |
339 })(); | |
340 | |
341 // Now check the case with array of holes and some elements on prototype. | |
342 (function() { | |
343 var len = 9; | |
344 | |
345 var at3 = "@3"; | |
346 var at7 = "@7"; | |
347 | |
348 for (var i = 0; i < 7; i++) { | |
349 var array = new Array(len); | |
350 var array_proto = []; | |
351 array_proto[3] = at3; | |
352 array_proto[7] = at7; | |
353 array.__proto__ = array_proto; | |
354 | |
355 var spliced = array.splice(2, 2, 'one', undefined, 'two'); | |
356 | |
357 // Second hole (at index 3) of array turns into | |
358 // value of Array.prototype[3] while copying. | |
359 assertEquals([, at3], spliced); | |
360 assertEquals([, , 'one', undefined, 'two', , , at7, at7, ,], array); | |
361 | |
362 // ... but array[3] and array[7] is actually a hole: | |
363 assertTrue(delete array_proto[3]); | |
364 assertEquals(undefined, array[3]); | |
365 assertTrue(delete array_proto[7]); | |
366 assertEquals(undefined, array[7]); | |
367 | |
368 // and now check hasOwnProperty | |
369 assertFalse(array.hasOwnProperty(0), "array.hasOwnProperty(0)"); | |
370 assertFalse(array.hasOwnProperty(1), "array.hasOwnProperty(1)"); | |
371 assertTrue(array.hasOwnProperty(2)); | |
372 assertTrue(array.hasOwnProperty(3)); | |
373 assertTrue(array.hasOwnProperty(4)); | |
374 assertFalse(array.hasOwnProperty(5), "array.hasOwnProperty(5)"); | |
375 assertFalse(array.hasOwnProperty(6), "array.hasOwnProperty(6)"); | |
376 assertFalse(array.hasOwnProperty(7), "array.hasOwnProperty(7)"); | |
377 assertTrue(array.hasOwnProperty(8)); | |
378 assertFalse(array.hasOwnProperty(9), "array.hasOwnProperty(9)"); | |
379 | |
380 // and now check couple of indices above length. | |
381 assertFalse(array.hasOwnProperty(10), "array.hasOwnProperty(10)"); | |
382 assertFalse(array.hasOwnProperty(15), "array.hasOwnProperty(15)"); | |
383 assertFalse(array.hasOwnProperty(31), "array.hasOwnProperty(31)"); | |
384 assertFalse(array.hasOwnProperty(63), "array.hasOwnProperty(63)"); | |
385 assertFalse(array.hasOwnProperty(Math.pow(2, 32) - 2), | |
386 "array.hasOwnProperty(Math.pow(2, 32) - 2)"); | |
387 } | |
388 })(); | |
389 | |
390 // Now check the case with array of holes and some elements on prototype. | |
391 (function() { | |
392 var len = 9; | |
393 | |
394 var at3 = "@3"; | |
395 var at7 = "@7"; | |
396 | |
397 for (var i = 0; i < 7; i++) { | |
398 var array = new Array(len); | |
399 Array.prototype[3] = at3; | |
400 Array.prototype[7] = at7; | |
401 | |
402 var spliced = array.splice(2, 2, 'one', undefined, 'two'); | |
403 | |
404 // Second hole (at index 3) of array turns into | |
405 // value of Array.prototype[3] while copying. | |
406 assertEquals([, at3], spliced); | |
407 assertEquals([, , 'one', undefined, 'two', , , at7, at7, ,], array); | |
408 | |
409 // ... but array[3] and array[7] is actually a hole: | |
410 assertTrue(delete Array.prototype[3]); | |
411 assertEquals(undefined, array[3]); | |
412 assertTrue(delete Array.prototype[7]); | |
413 assertEquals(undefined, array[7]); | |
414 | |
415 // and now check hasOwnProperty | |
416 assertFalse(array.hasOwnProperty(0), "array.hasOwnProperty(0)"); | |
417 assertFalse(array.hasOwnProperty(1), "array.hasOwnProperty(1)"); | |
418 assertTrue(array.hasOwnProperty(2)); | |
419 assertTrue(array.hasOwnProperty(3)); | |
420 assertTrue(array.hasOwnProperty(4)); | |
421 assertFalse(array.hasOwnProperty(5), "array.hasOwnProperty(5)"); | |
422 assertFalse(array.hasOwnProperty(6), "array.hasOwnProperty(6)"); | |
423 assertFalse(array.hasOwnProperty(7), "array.hasOwnProperty(7)"); | |
424 assertTrue(array.hasOwnProperty(8)); | |
425 assertFalse(array.hasOwnProperty(9), "array.hasOwnProperty(9)"); | |
426 | |
427 // and now check couple of indices above length. | |
428 assertFalse(array.hasOwnProperty(10), "array.hasOwnProperty(10)"); | |
429 assertFalse(array.hasOwnProperty(15), "array.hasOwnProperty(15)"); | |
430 assertFalse(array.hasOwnProperty(31), "array.hasOwnProperty(31)"); | |
431 assertFalse(array.hasOwnProperty(63), "array.hasOwnProperty(63)"); | |
432 assertFalse(array.hasOwnProperty(Math.pow(2, 32) - 2), | |
433 "array.hasOwnProperty(Math.pow(2, 32) - 2)"); | |
434 } | |
435 })();`; | |
436 | |
437 | |
438 | |
439 Protocol.Runtime.evaluate({ expression: expression }) | |
440 .then(function() {InspectorTest.completeTest();}); | |
OLD | NEW |