summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/basic/array-copyWithin.js
blob: 113613b38b49ce25ca66491fbdc2a6e37592b7e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Tests for Array#copyWithin

load(libdir + "asserts.js");

assertEq(Array.prototype.copyWithin.length, 2);

// works with two arguments
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 3), [1, 4, 5, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 2), [1, 3, 4, 5, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(2, 2), [1, 2, 3, 4, 5]);

// works with three arguments
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 3, 4), [1, 4, 3, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 2, 4), [1, 3, 4, 4, 5]);

// works with negative arguments
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, -2), [4, 5, 3, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, -2, -1), [4, 2, 3, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3, -2), [1, 3, 3, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3, -1), [1, 3, 4, 4, 5]);
assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3), [1, 3, 4, 5, 5]);

// works with array-like objects
var args = (function () { return Array.prototype.slice.call(arguments); }(1, 2, 3));
var argsClass = Object.prototype.toString.call(args);
assertDeepEq(args, [1, 2, 3]);
Array.prototype.copyWithin.call(args, -2, 0);
assertDeepEq(args, [1, 1, 2]);
assertDeepEq(Object.prototype.toString.call(args), argsClass);

// throws on null/undefined values
assertThrowsInstanceOf(function() {
  Array.prototype.copyWithin.call(null, 0, 3);
}, TypeError, "Assert that copyWithin fails if this value is null");

assertThrowsInstanceOf(function() {
  Array.prototype.copyWithin.call(undefined, 0, 3);
}, TypeError, "Assert that copyWithin fails if this value is undefined");

// test with this value as string
assertThrowsInstanceOf(function() {
  Array.prototype.copyWithin.call("hello world", 0, 3);
}, TypeError, "Assert that copyWithin fails if this value is string");

// test with this value as number
assertDeepEq(Array.prototype.copyWithin.call(34, 0, 3), new Number(34));

// test with this value as TypedArray
var buffer = new ArrayBuffer(16);
var int32View = new Int32Array(buffer);
for (var i=0; i<int32View.length; i++) {
  int32View[i] = i*2;
}
assertDeepEq(Array.prototype.copyWithin.call(int32View, 0, 1), new Int32Array([2, 4, 6, 6]));

// if arguments object is sloppy, copyWithin must move the arguments around
function f(a, b, c, d, e) {
  [].copyWithin.call(arguments, 1, 3);
  return [a, b, c, d, e];
}
assertDeepEq(f(1, 2, 3, 4, 5), [1, 4, 5, 4, 5]);

// test with target > start on 2 arguments
assertDeepEq([1, 2, 3, 4, 5].copyWithin(3, 0), [1, 2, 3, 1, 2]);

// test with target > start on 3 arguments
assertDeepEq([1, 2, 3, 4, 5].copyWithin(3, 0, 4), [1, 2, 3, 1, 2]);

// test on array with holes
var arr = new Array(6);
for (var i = 0; i < arr.length; i += 2) {
  arr[i] = i;
}
assertDeepEq(arr.copyWithin(0, 3), [, 4, , , 4, , ]);

// test on fractional arguments
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0.2, 3.9), [4, 5, 3, 4, 5]);

// test with -0
assertDeepEq([1, 2, 3, 4, 5].copyWithin(-0, 3), [4, 5, 3, 4, 5]);

// test with arguments more than this.length
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 7), [1, 2, 3, 4, 5]);

// test with arguments less than -this.length
assertDeepEq([1, 2, 3, 4, 5].copyWithin(-7, 0), [1, 2, 3, 4, 5]);

// test with arguments equal to -this.length
assertDeepEq([1, 2, 3, 4, 5].copyWithin(-5, 0), [1, 2, 3, 4, 5]);

// test on empty array
assertDeepEq([].copyWithin(0, 3), []);

// test with target range being shorter than end - start
assertDeepEq([1, 2, 3, 4, 5].copyWithin(2, 1, 4), [1, 2, 2, 3, 4]);

// test overlapping ranges
arr = [1, 2, 3, 4, 5];
arr.copyWithin(2, 1, 4);
assertDeepEq(arr.copyWithin(2, 1, 4), [1, 2, 2, 2, 3]);

// check that delete is strict
arr = [1, , 3, , 4, 5];
Object.freeze(arr);
assertThrowsInstanceOf(function() {
  arr.copyWithin(2, 1, 4);
}, TypeError, "Assert that delete is strict in copyWithin");

// test with a proxy object
var proxyObj = {
  get: function(recipient, name) {
    return recipient[name] + 2;
  }
};

var p = new Proxy([1, 2, 3, 4, 5], proxyObj);
Array.prototype.copyWithin.call(p, 0, 3);
for (name of Object.getOwnPropertyNames(p)) {
    print(name + ": " + JSON.stringify(Object.getOwnPropertyDescriptor(p, name)));
}

assertDeepEq(p, [6, 7, , , 5]);

// test if we throw in between
arr = [1, 2, 3, 4, 5];
Object.defineProperty(arr, 1, {
  set: function () {
    throw new Error("Boom!");
  }
});

assertThrowsInstanceOf(function() {
  arr.copyWithin(1, 3);
}, Error, "Throwing in between.");
assertEq(arr[0], 1);
assertEq(arr[1], undefined);
assertEq(arr[2], 3);
assertEq(arr[3], 4);
assertEq(arr[4], 5);

// undefined as third argument
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, undefined), [4, 5, 3, 4, 5]);

// test that this.length is called only once
arr = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5};
var count = 0;
Object.defineProperty(arr, "length", {
  get: function () {
    count++;
  }
});
Array.prototype.copyWithin.call(arr, 1, 3);
assertEq(count, 1);

count = 0;
Array.prototype.copyWithin.call(arr, 1, 3, 4);
assertEq(count, 1);

var large = 10000;

// test on a large array
arr = new Array(large);
assertDeepEq(arr.copyWithin(45, 900), arr);

// test on floating point numbers
for (var i = 0; i < large; i++) {
  arr[i] = Math.random();
}
arr.copyWithin(45, 900);

// test on array of objects
for (var i = 0; i < large; i++) {
  arr[i] = { num: Math.random() };
}
arr.copyWithin(45, 900);

// test array length remains same
assertEq(arr.length, large);

// test null on third argument is handled correctly
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, null), [1, 2, 3, 4, 5]);

// tamper the global Object prototype and test this works
Object.prototype[2] = 1;
assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]);