// Copyright 2010 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Check that unshifting array of holes keeps the original array // as array of holes (function() { var array = new Array(10); assertEquals(13, array.unshift('1st', '2ns', '3rd')); assertTrue(0 in array); assertTrue(1 in array); assertTrue(2 in array); assertFalse(3 in array); })(); // Check that unshift with no args has no side-effects. (function() { var len = 3; var array = new Array(len); var at0 = '@0'; var at2 = '@2'; Array.prototype[0] = at0; Array.prototype[2] = at2; // array owns nothing... assertFalse(array.hasOwnProperty(0)); assertFalse(array.hasOwnProperty(1)); assertFalse(array.hasOwnProperty(2)); // ... but sees values from Array.prototype assertEquals(array[0], at0); assertEquals(array[1], undefined); assertEquals(array[2], at2); assertEquals(len, array.unshift()); assertTrue(delete Array.prototype[0]); assertTrue(delete Array.prototype[2]); // array still owns nothing... assertFalse(array.hasOwnProperty(0)); assertFalse(array.hasOwnProperty(1)); assertFalse(array.hasOwnProperty(2)); // ... so they are not affected be delete. assertEquals(array[0], undefined); assertEquals(array[1], undefined); assertEquals(array[2], undefined); })(); // Now check the case with array of holes and some elements on prototype. (function() { var len = 9; var array = new Array(len); Array.prototype[3] = "@3"; Array.prototype[7] = "@7"; assertEquals(len, array.length); for (var i = 0; i < array.length; i++) { assertEquals(array[i], Array.prototype[i]); } assertEquals(len + 1, array.unshift('head')); assertEquals(len + 1, array.length); // Note that unshift copies values from prototype into the array. assertEquals(array[4], Array.prototype[3]); assertTrue(array.hasOwnProperty(4)); assertEquals(array[8], Array.prototype[7]); assertTrue(array.hasOwnProperty(8)); // ... but keeps the rest as holes: Array.prototype[5] = "@5"; assertEquals(array[5], Array.prototype[5]); assertFalse(array.hasOwnProperty(5)); assertEquals(array[3], Array.prototype[3]); assertFalse(array.hasOwnProperty(3)); assertEquals(array[7], Array.prototype[7]); assertFalse(array.hasOwnProperty(7)); assertTrue(delete Array.prototype[3]); assertTrue(delete Array.prototype[5]); assertTrue(delete Array.prototype[7]); })(); // Check that unshift with no args has no side-effects. (function() { var len = 3; var array = new Array(len); var at0 = '@0'; var at2 = '@2'; var array_proto = []; array_proto[0] = at0; array_proto[2] = at2; array.__proto__ = array_proto; // array owns nothing... assertFalse(array.hasOwnProperty(0)); assertFalse(array.hasOwnProperty(1)); assertFalse(array.hasOwnProperty(2)); // ... but sees values from array_proto. assertEquals(array[0], at0); assertEquals(array[1], undefined); assertEquals(array[2], at2); assertEquals(len, array.unshift()); // array still owns nothing. assertFalse(array.hasOwnProperty(0)); assertFalse(array.hasOwnProperty(1)); assertFalse(array.hasOwnProperty(2)); // ... but still sees values from array_proto. assertEquals(array[0], at0); assertEquals(array[1], undefined); assertEquals(array[2], at2); })(); // Now check the case with array of holes and some elements on prototype. (function() { var len = 9; var array = new Array(len); var array_proto = [] array_proto[3] = "@3"; array_proto[7] = "@7"; array.__proto__ = array_proto; assertEquals(len, array.length); for (var i = 0; i < array.length; i++) { assertEquals(array[i], array_proto[i]); } assertEquals(len + 1, array.unshift('head')); assertEquals(len + 1, array.length); // Note that unshift copies values from prototype into the array. assertEquals(array[4], array_proto[3]); assertTrue(array.hasOwnProperty(4)); assertEquals(array[8], array_proto[7]); assertTrue(array.hasOwnProperty(8)); // ... but keeps the rest as holes: array_proto[5] = "@5"; assertEquals(array[5], array_proto[5]); assertFalse(array.hasOwnProperty(5)); assertEquals(array[3], array_proto[3]); assertFalse(array.hasOwnProperty(3)); assertEquals(array[7], array_proto[7]); assertFalse(array.hasOwnProperty(7)); })(); // Check the behaviour when approaching maximal values for length. (function() { for (var i = 0; i < 7; i++) { try { let obj = { length: 2 ** 53 - 3}; Array.prototype.unshift.call(obj, 1, 2, 3, 4, 5); throw 'Should have thrown TypeError'; } catch (e) { assertTrue(e instanceof TypeError); } } })(); (function() { for (var i = 0; i < 7; i++) { var a = [6, 7, 8, 9]; a.unshift(1, 2, 3, 4, 5); assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a); } })(); // Check that non-enumerable elements are treated appropriately (function() { var array = [2, 3]; Object.defineProperty(array, '1', {enumerable: false}); array.unshift(1) assertEquals([1, 2, 3], array); array = [2]; array.length = 2; array.__proto__[1] = 3; Object.defineProperty(array.__proto__, '1', {enumerable: false}); array.unshift(1); assertEquals([1, 2, 3], array); })();