array-copyWithin.js (5791B)
1 // Tests for Array#copyWithin 2 3 load(libdir + "asserts.js"); 4 5 assertEq(Array.prototype.copyWithin.length, 2); 6 7 // works with two arguments 8 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]); 9 assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 3), [1, 4, 5, 4, 5]); 10 assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 2), [1, 3, 4, 5, 5]); 11 assertDeepEq([1, 2, 3, 4, 5].copyWithin(2, 2), [1, 2, 3, 4, 5]); 12 13 // works with three arguments 14 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]); 15 assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 3, 4), [1, 4, 3, 4, 5]); 16 assertDeepEq([1, 2, 3, 4, 5].copyWithin(1, 2, 4), [1, 3, 4, 4, 5]); 17 18 // works with negative arguments 19 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, -2), [4, 5, 3, 4, 5]); 20 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, -2, -1), [4, 2, 3, 4, 5]); 21 assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3, -2), [1, 3, 3, 4, 5]); 22 assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3, -1), [1, 3, 4, 4, 5]); 23 assertDeepEq([1, 2, 3, 4, 5].copyWithin(-4, -3), [1, 3, 4, 5, 5]); 24 25 // works with array-like objects 26 var args = (function () { return Array.prototype.slice.call(arguments); }(1, 2, 3)); 27 var argsClass = Object.prototype.toString.call(args); 28 assertDeepEq(args, [1, 2, 3]); 29 Array.prototype.copyWithin.call(args, -2, 0); 30 assertDeepEq(args, [1, 1, 2]); 31 assertDeepEq(Object.prototype.toString.call(args), argsClass); 32 33 // throws on null/undefined values 34 assertThrowsInstanceOf(function() { 35 Array.prototype.copyWithin.call(null, 0, 3); 36 }, TypeError, "Assert that copyWithin fails if this value is null"); 37 38 assertThrowsInstanceOf(function() { 39 Array.prototype.copyWithin.call(undefined, 0, 3); 40 }, TypeError, "Assert that copyWithin fails if this value is undefined"); 41 42 // test with this value as string 43 assertThrowsInstanceOf(function() { 44 Array.prototype.copyWithin.call("hello world", 0, 3); 45 }, TypeError, "Assert that copyWithin fails if this value is string"); 46 47 // test with this value as number 48 assertDeepEq(Array.prototype.copyWithin.call(34, 0, 3), new Number(34)); 49 50 // test with this value as TypedArray 51 var buffer = new ArrayBuffer(16); 52 var int32View = new Int32Array(buffer); 53 for (var i=0; i<int32View.length; i++) { 54 int32View[i] = i*2; 55 } 56 assertDeepEq(Array.prototype.copyWithin.call(int32View, 0, 1), new Int32Array([2, 4, 6, 6])); 57 58 // if arguments object is sloppy, copyWithin must move the arguments around 59 function f(a, b, c, d, e) { 60 [].copyWithin.call(arguments, 1, 3); 61 return [a, b, c, d, e]; 62 } 63 assertDeepEq(f(1, 2, 3, 4, 5), [1, 4, 5, 4, 5]); 64 65 // test with target > start on 2 arguments 66 assertDeepEq([1, 2, 3, 4, 5].copyWithin(3, 0), [1, 2, 3, 1, 2]); 67 68 // test with target > start on 3 arguments 69 assertDeepEq([1, 2, 3, 4, 5].copyWithin(3, 0, 4), [1, 2, 3, 1, 2]); 70 71 // test on array with holes 72 var arr = new Array(6); 73 for (var i = 0; i < arr.length; i += 2) { 74 arr[i] = i; 75 } 76 assertDeepEq(arr.copyWithin(0, 3), [, 4, , , 4, , ]); 77 78 // test on fractional arguments 79 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0.2, 3.9), [4, 5, 3, 4, 5]); 80 81 // test with -0 82 assertDeepEq([1, 2, 3, 4, 5].copyWithin(-0, 3), [4, 5, 3, 4, 5]); 83 84 // test with arguments more than this.length 85 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 7), [1, 2, 3, 4, 5]); 86 87 // test with arguments less than -this.length 88 assertDeepEq([1, 2, 3, 4, 5].copyWithin(-7, 0), [1, 2, 3, 4, 5]); 89 90 // test with arguments equal to -this.length 91 assertDeepEq([1, 2, 3, 4, 5].copyWithin(-5, 0), [1, 2, 3, 4, 5]); 92 93 // test on empty array 94 assertDeepEq([].copyWithin(0, 3), []); 95 96 // test with target range being shorter than end - start 97 assertDeepEq([1, 2, 3, 4, 5].copyWithin(2, 1, 4), [1, 2, 2, 3, 4]); 98 99 // test overlapping ranges 100 arr = [1, 2, 3, 4, 5]; 101 arr.copyWithin(2, 1, 4); 102 assertDeepEq(arr.copyWithin(2, 1, 4), [1, 2, 2, 2, 3]); 103 104 // check that delete is strict 105 arr = [1, , 3, , 4, 5]; 106 Object.freeze(arr); 107 assertThrowsInstanceOf(function() { 108 arr.copyWithin(2, 1, 4); 109 }, TypeError, "Assert that delete is strict in copyWithin"); 110 111 // test with a proxy object 112 var proxyObj = { 113 get: function(recipient, name) { 114 return recipient[name] + 2; 115 } 116 }; 117 118 var p = new Proxy([1, 2, 3, 4, 5], proxyObj); 119 Array.prototype.copyWithin.call(p, 0, 3); 120 for (name of Object.getOwnPropertyNames(p)) { 121 print(name + ": " + JSON.stringify(Object.getOwnPropertyDescriptor(p, name))); 122 } 123 124 assertDeepEq(p, [6, 7, , , 5]); 125 126 // test if we throw in between 127 arr = [1, 2, 3, 4, 5]; 128 Object.defineProperty(arr, 1, { 129 set: function () { 130 throw new Error("Boom!"); 131 } 132 }); 133 134 assertThrowsInstanceOf(function() { 135 arr.copyWithin(1, 3); 136 }, Error, "Throwing in between."); 137 assertEq(arr[0], 1); 138 assertEq(arr[1], undefined); 139 assertEq(arr[2], 3); 140 assertEq(arr[3], 4); 141 assertEq(arr[4], 5); 142 143 // undefined as third argument 144 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, undefined), [4, 5, 3, 4, 5]); 145 146 // test that this.length is called only once 147 arr = {0: 1, 1: 2, 2: 3, 3: 4, 4: 5}; 148 var count = 0; 149 Object.defineProperty(arr, "length", { 150 get: function () { 151 count++; 152 } 153 }); 154 Array.prototype.copyWithin.call(arr, 1, 3); 155 assertEq(count, 1); 156 157 count = 0; 158 Array.prototype.copyWithin.call(arr, 1, 3, 4); 159 assertEq(count, 1); 160 161 var large = 10000; 162 163 // test on a large array 164 arr = new Array(large); 165 assertDeepEq(arr.copyWithin(45, 900), arr); 166 167 // test on floating point numbers 168 for (var i = 0; i < large; i++) { 169 arr[i] = Math.random(); 170 } 171 arr.copyWithin(45, 900); 172 173 // test on array of objects 174 for (var i = 0; i < large; i++) { 175 arr[i] = { num: Math.random() }; 176 } 177 arr.copyWithin(45, 900); 178 179 // test array length remains same 180 assertEq(arr.length, large); 181 182 // test null on third argument is handled correctly 183 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3, null), [1, 2, 3, 4, 5]); 184 185 // tamper the global Object prototype and test this works 186 Object.prototype[2] = 1; 187 assertDeepEq([1, 2, 3, 4, 5].copyWithin(0, 3), [4, 5, 3, 4, 5]);