blob: ed52b7d5faa69cfd69be2431632e30688a37de70 [file] [log] [blame]
Ben Murdoch014dc512016-03-22 12:00:34 +00001// 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(function copyWithinArity() {
6 assertEquals(Array.prototype.copyWithin.length, 2);
7})();
8
9
10(function copyWithinTargetAndStart() {
11 // works with two arguemnts
12 assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3));
13 assertArrayEquals([1, 4, 5, 4, 5], [1, 2, 3, 4, 5].copyWithin(1, 3));
14 assertArrayEquals([1, 3, 4, 5, 5], [1, 2, 3, 4, 5].copyWithin(1, 2));
15 assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(2, 2));
16})();
17
18
19(function copyWithinTargetStartAndEnd() {
20 // works with three arguments
21 assertArrayEquals([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]);
22 assertArrayEquals([1, 2, 3, 4, 5].copyWithin(1, 3, 4), [1, 4, 3, 4, 5]);
23 assertArrayEquals([1, 2, 3, 4, 5].copyWithin(1, 2, 4), [1, 3, 4, 4, 5]);
24})();
25
26
27(function copyWithinNegativeRelativeOffsets() {
28 // works with negative arguments
29 assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, -2));
30 assertArrayEquals([4, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, -2, -1));
31 assertArrayEquals([1, 3, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3, -2));
32 assertArrayEquals([1, 3, 4, 4, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3, -1));
33 assertArrayEquals([1, 3, 4, 5, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3));
34 // test with arguments equal to -this.length
35 assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-5, 0));
36})();
37
38
39(function copyWithinArrayLikeValues() {
40 // works with array-like values
41 var args = (function () { return arguments; }(1, 2, 3));
42 Array.prototype.copyWithin.call(args, -2, 0);
43 assertArrayEquals([1, 1, 2], Array.prototype.slice.call(args));
44
45 // [[Class]] does not change
46 assertArrayEquals("[object Arguments]", Object.prototype.toString.call(args));
47})();
48
49
50(function copyWithinNullThis() {
51 // throws on null/undefined values
52 assertThrows(function() {
53 return Array.prototype.copyWithin.call(null, 0, 3);
54 }, TypeError);
55})();
56
57
58(function copyWithinUndefinedThis() {
59 assertThrows(function() {
60 return Array.prototype.copyWithin.call(undefined, 0, 3);
61 }, TypeError);
62})();
63
64
65// TODO(caitp): indexed properties of String are read-only and setting them
66// should throw in strict mode. See bug v8:4042
67// (function copyWithinStringThis() {
68// // test with this value as string
69// assertThrows(function() {
70// return Array.prototype.copyWithin.call("hello world", 0, 3);
71// }, TypeError);
72// })();
73
74
75(function copyWithinNumberThis() {
76 // test with this value as number
77 assertEquals(34, Array.prototype.copyWithin.call(34, 0, 3).valueOf());
78})();
79
80
81(function copyWithinSymbolThis() {
82 // test with this value as number
83 var sym = Symbol("test");
84 assertEquals(sym, Array.prototype.copyWithin.call(sym, 0, 3).valueOf());
85})();
86
87
88(function copyyWithinTypedArray() {
89 // test with this value as TypedArray
90 var buffer = new ArrayBuffer(16);
91 var int32View = new Int32Array(buffer);
92 for (var i=0; i<int32View.length; i++) {
93 int32View[i] = i*2;
94 }
95 assertArrayEquals(new Int32Array([2, 4, 6, 6]),
96 Array.prototype.copyWithin.call(int32View, 0, 1));
97})();
98
99
100(function copyWithinSloppyArguments() {
101 // if arguments object is sloppy, copyWithin must move the arguments around
102 function f(a, b, c, d, e) {
103 [].copyWithin.call(arguments, 1, 3);
104 return [a, b, c, d, e];
105 }
106 assertArrayEquals([1, 4, 5, 4, 5], f(1, 2, 3, 4, 5));
107})();
108
109
110(function copyWithinStartLessThanTarget() {
111 // test with target > start on 2 arguments
112 assertArrayEquals([1, 2, 3, 1, 2], [1, 2, 3, 4, 5].copyWithin(3, 0));
113
114 // test with target > start on 3 arguments
115 assertArrayEquals([1, 2, 3, 1, 2], [1, 2, 3, 4, 5].copyWithin(3, 0, 4));
116})();
117
118
119(function copyWithinArrayWithHoles() {
120 // test on array with holes
121 var arr = new Array(6);
122 for (var i = 0; i < arr.length; i += 2) {
123 arr[i] = i;
124 }
125 assertArrayEquals([, 4, , , 4, , ], arr.copyWithin(0, 3));
126})();
127
128
129(function copyWithinArrayLikeWithHoles() {
130 // test on array-like object with holes
131 assertArrayEquals({
132 length: 6,
133 1: 4,
134 4: 4
135 }, Array.prototype.copyWithin.call({
136 length: 6,
137 0: 0,
138 2: 2,
139 4: 4
140 }, 0, 3));
141})();
142
143
144(function copyWithinNonIntegerRelativeOffsets() {
145 // test on fractional arguments
146 assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0.2, 3.9));
147})();
148
149
150(function copyWithinNegativeZeroTarget() {
151 // test with -0
152 assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-0, 3));
153})();
154
155
156(function copyWithinTargetOutsideStart() {
157 // test with arguments more than this.length
158 assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 7));
159
160 // test with arguments less than -this.length
161 assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-7, 0));
162})();
163
164
165(function copyWithinEmptyArray() {
166 // test on empty array
167 assertArrayEquals([], [].copyWithin(0, 3));
168})();
169
170
171(function copyWithinTargetCutOff() {
172 // test with target range being shorter than end - start
173 assertArrayEquals([1, 2, 2, 3, 4], [1, 2, 3, 4, 5].copyWithin(2, 1, 4));
174})();
175
176
177(function copyWithinOverlappingRanges() {
178 // test overlapping ranges
179 var arr = [1, 2, 3, 4, 5];
180 arr.copyWithin(2, 1, 4);
181 assertArrayEquals([1, 2, 2, 2, 3], arr.copyWithin(2, 1, 4));
182})();
183
184
185(function copyWithinStrictDelete() {
186 // check that [[Delete]] is strict (non-extensible via freeze)
187 assertThrows(function() {
188 return Object.freeze([1, , 3, , 4, 5]).copyWithin(2, 1, 4);
189 }, TypeError);
190
191 // check that [[Delete]] is strict (non-extensible via seal)
192 assertThrows(function() {
193 return Object.seal([1, , 3, , 4, 5]).copyWithin(2, 1, 4);
194 }, TypeError);
195
196 // check that [[Delete]] is strict (non-extensible via preventExtensions)
197 assertThrows(function() {
198 return Object.preventExtensions([1, , 3, , 4, 5]).copyWithin(2, 1, 4);
199 }, TypeError);
200})();
201
202
203(function copyWithinStrictSet() {
204 // check that [[Set]] is strict (non-extensible via freeze)
205 assertThrows(function() {
206 return Object.freeze([1, 2, 3, 4, 5]).copyWithin(0, 3);
207 }, TypeError);
208
209 // check that [[Set]] is strict (non-extensible via seal)
210 assertThrows(function() {
211 return Object.seal([, 2, 3, 4, 5]).copyWithin(0, 3);
212 }, TypeError);
213
214 // check that [[Set]] is strict (non-extensible via preventExtensions)
215 assertThrows(function() {
216 return Object.preventExtensions([ , 2, 3, 4, 5]).copyWithin(0, 3);
217 }, TypeError);
218})();
219
220
221(function copyWithinSetterThrows() {
222 function Boom() {}
223 // test if we throw in between
224 var arr = Object.defineProperty([1, 2, 3, 4, 5], 1, {
225 set: function () {
226 throw new Boom();
227 }
228 });
229
230 assertThrows(function() {
231 return arr.copyWithin(1, 3);
232 }, Boom);
233
234 assertArrayEquals([1, , 3, 4, 5], arr);
235})();
236
237
238(function copyWithinDefaultEnd() {
239 // undefined as third argument
240 assertArrayEquals(
241 [4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3, undefined));
242})();
243
244
245(function copyWithinGetLengthOnce() {
246 // test that this.length is called only once
247 var count = 0;
248 var arr = Object.defineProperty({ 0: 1, 1: 2, 2: 3, 3: 4, 4: 5 }, "length", {
249 get: function () {
250 count++;
251 return 5;
252 }
253 });
254 Array.prototype.copyWithin.call(arr, 1, 3);
255 assertEquals(1, count);
256
257 Array.prototype.copyWithin.call(arr, 1, 3, 4);
258 assertEquals(2, count);
259})();
260
261
262(function copyWithinLargeArray() {
263 var large = 10000;
264
265 // test on a large array
266 var arr = new Array(large);
267 assertArrayEquals(arr, arr.copyWithin(45, 9000));
268
269 var expected = new Array(large);
270 // test on floating point numbers
271 for (var i = 0; i < large; i++) {
272 arr[i] = Math.random();
273 expected[i] = arr[i];
274 if (i >= 9000) {
275 expected[(i - 9000) + 45] = arr[i];
276 }
277 }
278 assertArrayEquals(expected, arr.copyWithin(45, 9000));
279
280 // test on array of objects
281 for (var i = 0; i < large; i++) {
282 arr[i] = { num: Math.random() };
283 } + 45
284 arr.copyWithin(45, 9000);
285
286 // test copied by reference
287 for (var i = 9000; i < large; ++i) {
288 assertSame(arr[(i - 9000) + 45], arr[i]);
289 }
290
291 // test array length remains same
292 assertEquals(large, arr.length);
293})();
294
295
296(function copyWithinSuperLargeLength() {
297 // 2^53 - 1 is the maximum value returned from ToLength()
298 var large = Math.pow(2, 53) - 1;
299 var object = { length: large };
300
301 // Initialize last 10 entries
302 for (var i = 1; i <= 10; ++i) {
303 object[(large - 11) + i] = { num: i };
304 }
305
306 Array.prototype.copyWithin.call(object, 1, large - 10);
307
308 // Test copied values
309 for (var i = 1; i <= 10; ++i) {
310 var old_ref = object[(large - 11) + i];
311 var new_ref = object[i];
312 assertSame(old_ref, new_ref);
313 assertSame(new_ref.num, i);
314 }
315
316 // Assert length has not changed
317 assertEquals(large, object.length);
318})();
319
320
321(function copyWithinNullEnd() {
322 // test null on third argument is converted to +0
323 assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3, null));
324})();
325
326
327(function copyWithinElementsInObjectsPrototype() {
328 // tamper the global Object prototype and test this works
329 Object.prototype[2] = 1;
330 assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3));
331 delete Object.prototype[2];
332
333 Object.prototype[3] = "FAKE";
334 assertArrayEquals(["FAKE", 5, 3, "FAKE", 5], [1, 2, 3, , 5].copyWithin(0, 3));
335 delete Object.prototype[3];
336})();