Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(669)

Side by Side Diff: test/mjsunit/harmony/array-concat.js

Issue 771483002: Implement ES6 @@isConcatSpreadable (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rename IterateExternalArrayElements, add tests which hit Fixed<Type>Array cases Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/runtime/runtime-array.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 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: --harmony-arrays --harmony-classes
6
7 (function testArrayConcatArity() {
8 "use strict";
9 assertEquals(1, Array.prototype.concat.length);
10 })();
11
12
13 (function testArrayConcatNoPrototype() {
14 "use strict";
15 assertEquals(void 0, Array.prototype.concat.prototype);
16 })();
17
18
19 (function testArrayConcatDescriptor() {
20 "use strict";
21 var desc = Object.getOwnPropertyDescriptor(Array.prototype, 'concat');
22 assertEquals(false, desc.enumerable);
23 })();
24
25
26 (function testConcatArrayLike() {
27 "use strict";
28 var obj = {
29 "length": 6,
30 "1": "A",
31 "3": "B",
32 "5": "C"
33 };
34 obj[Symbol.isConcatSpreadable] = true;
35 var obj2 = { length: 3, "0": "0", "1": "1", "2": "2" };
36 var arr = ["X", "Y", "Z"];
37 assertEquals([void 0, "A", void 0, "B", void 0, "C",
38 { "length": 3, "0": "0", "1": "1", "2": "2" },
39 "X", "Y", "Z"], Array.prototype.concat.call(obj, obj2, arr));
40 })();
41
42
43 (function testConcatHoleyArray() {
44 "use strict";
45 var arr = [];
46 arr[4] = "Item 4";
47 arr[8] = "Item 8";
48 var arr2 = [".", "!", "?"];
49 assertEquals([void 0, void 0, void 0, void 0, "Item 4", void 0, void 0,
50 void 0, "Item 8", ".", "!", "?"], arr.concat(arr2));
51 })();
52
53
54 (function testIsConcatSpreadableGetterThrows() {
55 "use strict";
56 function MyError() {}
57 var obj = {};
58 Object.defineProperty(obj, Symbol.isConcatSpreadable, {
59 get: function() { throw new MyError(); }
60 });
61
62 assertThrows(function() {
63 [].concat(obj);
64 }, MyError);
65
66 assertThrows(function() {
67 Array.prototype.concat.call(obj, 1, 2, 3);
68 }, MyError);
69 })();
70
71
72 (function testConcatLengthThrows() {
73 "use strict";
74 function MyError() {}
75 var obj = {};
76 obj[Symbol.isConcatSpreadable] = true;
77 Object.defineProperty(obj, "length", {
78 get: function() { throw new MyError(); }
79 });
80
81 assertThrows(function() {
82 [].concat(obj);
83 }, MyError);
84
85 assertThrows(function() {
86 Array.prototype.concat.call(obj, 1, 2, 3);
87 }, MyError);
88 })();
89
90
91 (function testConcatArraySubclass() {
92 "use strict";
93 // TODO(caitp): when concat is called on instances of classes which extend
94 // Array, they should:
95 //
96 // - return an instance of the class, rather than an Array instance (if from
97 // same Realm)
98 // - always treat such classes as concat-spreadable
99 })();
100
101
102 (function testConcatNonArray() {
103 "use strict";
104 class NonArray {
105 constructor() { Array.apply(this, arguments); }
106 };
107
108 var obj = new NonArray(1,2,3);
109 var result = Array.prototype.concat.call(obj, 4, 5, 6);
110 assertEquals(Array, result.constructor);
111 assertEquals([obj,4,5,6], result);
112 assertFalse(result instanceof NonArray);
113 })();
114
115
116 function testConcatTypedArray(type, elems, modulo) {
117 "use strict";
118 var items = new Array(elems);
119 var ta_by_len = new type(elems);
120 for (var i = 0; i < elems; ++i) {
121 ta_by_len[i] = items[i] = modulo === false ? i : elems % modulo;
122 }
123 var ta = new type(items);
124 assertEquals([ta, ta], [].concat(ta, ta));
125 ta[Symbol.isConcatSpreadable] = true;
126 assertEquals(items, [].concat(ta));
127
128 assertEquals([ta_by_len, ta_by_len], [].concat(ta_by_len, ta_by_len));
129 ta_by_len[Symbol.isConcatSpreadable] = true;
130 assertEquals(items, [].concat(ta_by_len));
131 }
132
133 (function testConcatSmallTypedArray() {
134 var max = [2^8, 2^16, 2^32, false, false];
135 [
136 Uint8Array,
137 Uint16Array,
138 Uint32Array,
139 Float32Array,
140 Float64Array
141 ].forEach(function(ctor, i) {
142 testConcatTypedArray(ctor, 1, max[i]);
143 });
144 })();
145
146
147 (function testConcatLargeTypedArray() {
148 var max = [2^8, 2^16, 2^32, false, false];
149 [
150 Uint8Array,
151 Uint16Array,
152 Uint32Array,
153 Float32Array,
154 Float64Array
155 ].forEach(function(ctor, i) {
156 testConcatTypedArray(ctor, 4000, max[i]);
157 });
158 })();
159
160
161 (function testConcatStrictArguments() {
162 var args = (function(a, b, c) { "use strict"; return arguments; })(1,2,3);
163 args[Symbol.isConcatSpreadable] = true;
164 assertEquals([1, 2, 3, 1, 2, 3], [].concat(args, args));
165 })();
166
167
168 (function testConcatSloppyArguments() {
169 var args = (function(a, b, c) { return arguments; })(1,2,3);
170 args[Symbol.isConcatSpreadable] = true;
171 assertEquals([1, 2, 3, 1, 2, 3], [].concat(args, args));
172 })();
173
174
175 (function testConcatSloppyArgumentsWithDupes() {
176 var args = (function(a, a, a) { return arguments; })(1,2,3);
177 args[Symbol.isConcatSpreadable] = true;
178 assertEquals([1, 2, 3, 1, 2, 3], [].concat(args, args));
179 })();
180
181
182 (function testConcatSloppyArgumentsThrows() {
183 function MyError() {}
184 var args = (function(a) { return arguments; })(1,2,3);
185 Object.defineProperty(args, 0, {
186 get: function() { throw new MyError(); }
187 });
188 args[Symbol.isConcatSpreadable] = true;
189 assertThrows(function() {
190 return [].concat(args, args);
191 }, MyError);
192 })();
193
194
195 (function testConcatHoleySloppyArguments() {
196 var args = (function(a) { return arguments; })(1,2,3);
197 delete args[1];
198 args[Symbol.isConcatSpreadable] = true;
199 assertEquals([1, void 0, 3, 1, void 0, 3], [].concat(args, args));
200 })();
201
202
203 // ES5 tests
204 (function testArrayConcatES5() {
205 "use strict";
206 var poses;
207 var pos;
208
209 poses = [140, 4000000000];
210 while (pos = poses.shift()) {
211 var a = new Array(pos);
212 var array_proto = [];
213 a.__proto__ = array_proto;
214 assertEquals(pos, a.length);
215 a.push('foo');
216 assertEquals(pos + 1, a.length);
217 var b = ['bar'];
218 var c = a.concat(b);
219 assertEquals(pos + 2, c.length);
220 assertEquals("undefined", typeof(c[pos - 1]));
221 assertEquals("foo", c[pos]);
222 assertEquals("bar", c[pos + 1]);
223
224 // Can we fool the system by putting a number in a string?
225 var onetwofour = "124";
226 a[onetwofour] = 'doo';
227 assertEquals(a[124], 'doo');
228 c = a.concat(b);
229 assertEquals(c[124], 'doo');
230
231 // If we put a number in the prototype, then the spec says it should be
232 // copied on concat.
233 array_proto["123"] = 'baz';
234 assertEquals(a[123], 'baz');
235
236 c = a.concat(b);
237 assertEquals(pos + 2, c.length);
238 assertEquals("baz", c[123]);
239 assertEquals("undefined", typeof(c[pos - 1]));
240 assertEquals("foo", c[pos]);
241 assertEquals("bar", c[pos + 1]);
242
243 // When we take the number off the prototype it disappears from a, but
244 // the concat put it in c itself.
245 array_proto["123"] = undefined;
246 assertEquals("undefined", typeof(a[123]));
247 assertEquals("baz", c[123]);
248
249 // If the element of prototype is shadowed, the element on the instance
250 // should be copied, but not the one on the prototype.
251 array_proto[123] = 'baz';
252 a[123] = 'xyz';
253 assertEquals('xyz', a[123]);
254 c = a.concat(b);
255 assertEquals('xyz', c[123]);
256
257 // Non-numeric properties on the prototype or the array shouldn't get
258 // copied.
259 array_proto.moe = 'joe';
260 a.ben = 'jerry';
261 assertEquals(a["moe"], 'joe');
262 assertEquals(a["ben"], 'jerry');
263 c = a.concat(b);
264 // ben was not copied
265 assertEquals("undefined", typeof(c.ben));
266
267 // When we take moe off the prototype it disappears from all arrays.
268 array_proto.moe = undefined;
269 assertEquals("undefined", typeof(c.moe));
270
271 // Negative indices don't get concated.
272 a[-1] = 'minus1';
273 assertEquals("minus1", a[-1]);
274 assertEquals("undefined", typeof(a[0xffffffff]));
275 c = a.concat(b);
276 assertEquals("undefined", typeof(c[-1]));
277 assertEquals("undefined", typeof(c[0xffffffff]));
278 assertEquals(c.length, a.length + 1);
279 }
280
281 poses = [140, 4000000000];
282 while (pos = poses.shift()) {
283 var a = new Array(pos);
284 assertEquals(pos, a.length);
285 a.push('foo');
286 assertEquals(pos + 1, a.length);
287 var b = ['bar'];
288 var c = a.concat(b);
289 assertEquals(pos + 2, c.length);
290 assertEquals("undefined", typeof(c[pos - 1]));
291 assertEquals("foo", c[pos]);
292 assertEquals("bar", c[pos + 1]);
293
294 // Can we fool the system by putting a number in a string?
295 var onetwofour = "124";
296 a[onetwofour] = 'doo';
297 assertEquals(a[124], 'doo');
298 c = a.concat(b);
299 assertEquals(c[124], 'doo');
300
301 // If we put a number in the prototype, then the spec says it should be
302 // copied on concat.
303 Array.prototype["123"] = 'baz';
304 assertEquals(a[123], 'baz');
305
306 c = a.concat(b);
307 assertEquals(pos + 2, c.length);
308 assertEquals("baz", c[123]);
309 assertEquals("undefined", typeof(c[pos - 1]));
310 assertEquals("foo", c[pos]);
311 assertEquals("bar", c[pos + 1]);
312
313 // When we take the number off the prototype it disappears from a, but
314 // the concat put it in c itself.
315 Array.prototype["123"] = undefined;
316 assertEquals("undefined", typeof(a[123]));
317 assertEquals("baz", c[123]);
318
319 // If the element of prototype is shadowed, the element on the instance
320 // should be copied, but not the one on the prototype.
321 Array.prototype[123] = 'baz';
322 a[123] = 'xyz';
323 assertEquals('xyz', a[123]);
324 c = a.concat(b);
325 assertEquals('xyz', c[123]);
326
327 // Non-numeric properties on the prototype or the array shouldn't get
328 // copied.
329 Array.prototype.moe = 'joe';
330 a.ben = 'jerry';
331 assertEquals(a["moe"], 'joe');
332 assertEquals(a["ben"], 'jerry');
333 c = a.concat(b);
334 // ben was not copied
335 assertEquals("undefined", typeof(c.ben));
336 // moe was not copied, but we can see it through the prototype
337 assertEquals("joe", c.moe);
338
339 // When we take moe off the prototype it disappears from all arrays.
340 Array.prototype.moe = undefined;
341 assertEquals("undefined", typeof(c.moe));
342
343 // Negative indices don't get concated.
344 a[-1] = 'minus1';
345 assertEquals("minus1", a[-1]);
346 assertEquals("undefined", typeof(a[0xffffffff]));
347 c = a.concat(b);
348 assertEquals("undefined", typeof(c[-1]));
349 assertEquals("undefined", typeof(c[0xffffffff]));
350 assertEquals(c.length, a.length + 1);
351
352 }
353
354 a = [];
355 c = a.concat('Hello');
356 assertEquals(1, c.length);
357 assertEquals("Hello", c[0]);
358 assertEquals("Hello", c.toString());
359
360 // Check that concat preserves holes.
361 var holey = [void 0,'a',,'c'].concat(['d',,'f',[0,,2],void 0])
362 assertEquals(9, holey.length); // hole in embedded array is ignored
363 for (var i = 0; i < holey.length; i++) {
364 if (i == 2 || i == 5) {
365 assertFalse(i in holey);
366 } else {
367 assertTrue(i in holey);
368 }
369 }
370
371 // Polluted prototype from prior tests.
372 delete Array.prototype[123];
373
374 // Check that concat reads getters in the correct order.
375 var arr1 = [,2];
376 var arr2 = [1,3];
377 var r1 = [].concat(arr1, arr2); // [,2,1,3]
378 assertEquals([,2,1,3], r1);
379
380 // Make first array change length of second array.
381 Object.defineProperty(arr1, 0, {get: function() {
382 arr2.push("X");
383 return undefined;
384 }, configurable: true})
385 var r2 = [].concat(arr1, arr2); // [undefined,2,1,3,"X"]
386 assertEquals([undefined,2,1,3,"X"], r2);
387
388 // Make first array change length of second array massively.
389 arr2.length = 2;
390 Object.defineProperty(arr1, 0, {get: function() {
391 arr2[500000] = "X";
392 return undefined;
393 }, configurable: true})
394 var r3 = [].concat(arr1, arr2); // [undefined,2,1,3,"X"]
395 var expected = [undefined,2,1,3];
396 expected[500000 + 2] = "X";
397
398 assertEquals(expected, r3);
399
400 var arr3 = [];
401 var trace = [];
402 var expectedTrace = []
403 function mkGetter(i) { return function() { trace.push(i); }; }
404 arr3.length = 10000;
405 for (var i = 0; i < 100; i++) {
406 Object.defineProperty(arr3, i * i, {get: mkGetter(i)});
407 expectedTrace[i] = i;
408 expectedTrace[100 + i] = i;
409 }
410 var r4 = [0].concat(arr3, arr3);
411 assertEquals(1 + arr3.length * 2, r4.length);
412 assertEquals(expectedTrace, trace);
413 })();
OLDNEW
« no previous file with comments | « src/runtime/runtime-array.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698