// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --harmony-arrays (function copyWithinArity() { assertEquals(Array.prototype.copyWithin.length, 2); })(); (function copyWithinTargetAndStart() { // works with two arguemnts assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3)); assertArrayEquals([1, 4, 5, 4, 5], [1, 2, 3, 4, 5].copyWithin(1, 3)); assertArrayEquals([1, 3, 4, 5, 5], [1, 2, 3, 4, 5].copyWithin(1, 2)); assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(2, 2)); })(); (function copyWithinTargetStartAndEnd() { // works with three arguments assertArrayEquals([1, 2, 3, 4, 5].copyWithin(0, 3, 4), [4, 2, 3, 4, 5]); assertArrayEquals([1, 2, 3, 4, 5].copyWithin(1, 3, 4), [1, 4, 3, 4, 5]); assertArrayEquals([1, 2, 3, 4, 5].copyWithin(1, 2, 4), [1, 3, 4, 4, 5]); })(); (function copyWithinNegativeRelativeOffsets() { // works with negative arguments assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, -2)); assertArrayEquals([4, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, -2, -1)); assertArrayEquals([1, 3, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3, -2)); assertArrayEquals([1, 3, 4, 4, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3, -1)); assertArrayEquals([1, 3, 4, 5, 5], [1, 2, 3, 4, 5].copyWithin(-4, -3)); // test with arguments equal to -this.length assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-5, 0)); })(); (function copyWithinArrayLikeValues() { // works with array-like values var args = (function () { return arguments; }(1, 2, 3)); Array.prototype.copyWithin.call(args, -2, 0); assertArrayEquals([1, 1, 2], Array.prototype.slice.call(args)); // [[Class]] does not change assertArrayEquals("[object Arguments]", Object.prototype.toString.call(args)); })(); (function copyWithinNullThis() { // throws on null/undefined values assertThrows(function() { return Array.prototype.copyWithin.call(null, 0, 3); }, TypeError); })(); (function copyWithinUndefinedThis() { assertThrows(function() { return Array.prototype.copyWithin.call(undefined, 0, 3); }, TypeError); })(); // TODO(caitp): indexed properties of String are read-only and setting them // should throw in strict mode. See bug v8:4042 // (function copyWithinStringThis() { // // test with this value as string // assertThrows(function() { // return Array.prototype.copyWithin.call("hello world", 0, 3); // }, TypeError); // })(); (function copyWithinNumberThis() { // test with this value as number assertEquals(34, Array.prototype.copyWithin.call(34, 0, 3).valueOf()); })(); (function copyWithinSymbolThis() { // test with this value as number var sym = Symbol("test"); assertEquals(sym, Array.prototype.copyWithin.call(sym, 0, 3).valueOf()); })(); (function copyyWithinTypedArray() { // test with this value as TypedArray var buffer = new ArrayBuffer(16); var int32View = new Int32Array(buffer); for (var i=0; i start on 2 arguments assertArrayEquals([1, 2, 3, 1, 2], [1, 2, 3, 4, 5].copyWithin(3, 0)); // test with target > start on 3 arguments assertArrayEquals([1, 2, 3, 1, 2], [1, 2, 3, 4, 5].copyWithin(3, 0, 4)); })(); (function copyWithinArrayWithHoles() { // test on array with holes var arr = new Array(6); for (var i = 0; i < arr.length; i += 2) { arr[i] = i; } assertArrayEquals([, 4, , , 4, , ], arr.copyWithin(0, 3)); })(); (function copyWithinArrayLikeWithHoles() { // test on array-like object with holes assertArrayEquals({ length: 6, 1: 4, 4: 4 }, Array.prototype.copyWithin.call({ length: 6, 0: 0, 2: 2, 4: 4 }, 0, 3)); })(); (function copyWithinNonIntegerRelativeOffsets() { // test on fractional arguments assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0.2, 3.9)); })(); (function copyWithinNegativeZeroTarget() { // test with -0 assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-0, 3)); })(); (function copyWithinTargetOutsideStart() { // test with arguments more than this.length assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 7)); // test with arguments less than -this.length assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(-7, 0)); })(); (function copyWithinEmptyArray() { // test on empty array assertArrayEquals([], [].copyWithin(0, 3)); })(); (function copyWithinTargetCutOff() { // test with target range being shorter than end - start assertArrayEquals([1, 2, 2, 3, 4], [1, 2, 3, 4, 5].copyWithin(2, 1, 4)); })(); (function copyWithinOverlappingRanges() { // test overlapping ranges var arr = [1, 2, 3, 4, 5]; arr.copyWithin(2, 1, 4); assertArrayEquals([1, 2, 2, 2, 3], arr.copyWithin(2, 1, 4)); })(); (function copyWithinStrictDelete() { // check that [[Delete]] is strict (non-extensible via freeze) assertThrows(function() { return Object.freeze([1, , 3, , 4, 5]).copyWithin(2, 1, 4); }, TypeError); // check that [[Delete]] is strict (non-extensible via seal) assertThrows(function() { return Object.seal([1, , 3, , 4, 5]).copyWithin(2, 1, 4); }, TypeError); // check that [[Delete]] is strict (non-extensible via preventExtensions) assertThrows(function() { return Object.preventExtensions([1, , 3, , 4, 5]).copyWithin(2, 1, 4); }, TypeError); })(); (function copyWithinStrictSet() { // check that [[Set]] is strict (non-extensible via freeze) assertThrows(function() { return Object.freeze([1, 2, 3, 4, 5]).copyWithin(0, 3); }, TypeError); // check that [[Set]] is strict (non-extensible via seal) assertThrows(function() { return Object.seal([, 2, 3, 4, 5]).copyWithin(0, 3); }, TypeError); // check that [[Set]] is strict (non-extensible via preventExtensions) assertThrows(function() { return Object.preventExtensions([ , 2, 3, 4, 5]).copyWithin(0, 3); }, TypeError); })(); (function copyWithinSetterThrows() { function Boom() {} // test if we throw in between var arr = Object.defineProperty([1, 2, 3, 4, 5], 1, { set: function () { throw new Boom(); } }); assertThrows(function() { return arr.copyWithin(1, 3); }, Boom); assertArrayEquals([1, , 3, 4, 5], arr); })(); (function copyWithinDefaultEnd() { // undefined as third argument assertArrayEquals( [4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3, undefined)); })(); (function copyWithinGetLengthOnce() { // test that this.length is called only once var count = 0; var arr = Object.defineProperty({ 0: 1, 1: 2, 2: 3, 3: 4, 4: 5 }, "length", { get: function () { count++; return 5; } }); Array.prototype.copyWithin.call(arr, 1, 3); assertEquals(1, count); Array.prototype.copyWithin.call(arr, 1, 3, 4); assertEquals(2, count); })(); (function copyWithinLargeArray() { var large = 10000; // test on a large array var arr = new Array(large); assertArrayEquals(arr, arr.copyWithin(45, 9000)); var expected = new Array(large); // test on floating point numbers for (var i = 0; i < large; i++) { arr[i] = Math.random(); expected[i] = arr[i]; if (i >= 9000) { expected[(i - 9000) + 45] = arr[i]; } } assertArrayEquals(expected, arr.copyWithin(45, 9000)); // test on array of objects for (var i = 0; i < large; i++) { arr[i] = { num: Math.random() }; } + 45 arr.copyWithin(45, 9000); // test copied by reference for (var i = 9000; i < large; ++i) { assertSame(arr[(i - 9000) + 45], arr[i]); } // test array length remains same assertEquals(large, arr.length); })(); (function copyWithinSuperLargeLength() { // 2^53 - 1 is the maximum value returned from ToLength() var large = Math.pow(2, 53) - 1; var object = { length: large }; // Initialize last 10 entries for (var i = 1; i <= 10; ++i) { object[(large - 11) + i] = { num: i }; } Array.prototype.copyWithin.call(object, 1, large - 10); // Test copied values for (var i = 1; i <= 10; ++i) { var old_ref = object[(large - 11) + i]; var new_ref = object[i]; assertSame(old_ref, new_ref); assertSame(new_ref.num, i); } // Assert length has not changed assertEquals(large, object.length); })(); (function copyWithinNullEnd() { // test null on third argument is converted to +0 assertArrayEquals([1, 2, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3, null)); })(); (function copyWithinElementsInObjectsPrototype() { // tamper the global Object prototype and test this works Object.prototype[2] = 1; assertArrayEquals([4, 5, 3, 4, 5], [1, 2, 3, 4, 5].copyWithin(0, 3)); delete Object.prototype[2]; Object.prototype[3] = "FAKE"; assertArrayEquals(["FAKE", 5, 3, "FAKE", 5], [1, 2, 3, , 5].copyWithin(0, 3)); delete Object.prototype[3]; })();