1// Copyright 2010 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Check that unshifting array of holes keeps the original array 29// as array of holes 30(function() { 31 var array = new Array(10); 32 assertEquals(13, array.unshift('1st', '2ns', '3rd')); 33 assertTrue(0 in array); 34 assertTrue(1 in array); 35 assertTrue(2 in array); 36 assertFalse(3 in array); 37})(); 38 39 40// Check that unshift with no args has no side-effects. 41(function() { 42 var len = 3; 43 var array = new Array(len); 44 45 var at0 = '@0'; 46 var at2 = '@2'; 47 48 Array.prototype[0] = at0; 49 Array.prototype[2] = at2; 50 51 // array owns nothing... 52 assertFalse(array.hasOwnProperty(0)); 53 assertFalse(array.hasOwnProperty(1)); 54 assertFalse(array.hasOwnProperty(2)); 55 56 // ... but sees values from Array.prototype 57 assertEquals(array[0], at0); 58 assertEquals(array[1], undefined); 59 assertEquals(array[2], at2); 60 61 assertEquals(len, array.unshift()); 62 63 assertTrue(delete Array.prototype[0]); 64 assertTrue(delete Array.prototype[2]); 65 66 // array still owns nothing... 67 assertFalse(array.hasOwnProperty(0)); 68 assertFalse(array.hasOwnProperty(1)); 69 assertFalse(array.hasOwnProperty(2)); 70 71 // ... so they are not affected be delete. 72 assertEquals(array[0], undefined); 73 assertEquals(array[1], undefined); 74 assertEquals(array[2], undefined); 75})(); 76 77 78// Now check the case with array of holes and some elements on prototype. 79(function() { 80 var len = 9; 81 var array = new Array(len); 82 Array.prototype[3] = "@3"; 83 Array.prototype[7] = "@7"; 84 85 assertEquals(len, array.length); 86 for (var i = 0; i < array.length; i++) { 87 assertEquals(array[i], Array.prototype[i]); 88 } 89 90 assertEquals(len + 1, array.unshift('head')); 91 92 assertEquals(len + 1, array.length); 93 // Note that unshift copies values from prototype into the array. 94 assertEquals(array[4], Array.prototype[3]); 95 assertTrue(array.hasOwnProperty(4)); 96 97 assertEquals(array[8], Array.prototype[7]); 98 assertTrue(array.hasOwnProperty(8)); 99 100 // ... but keeps the rest as holes: 101 Array.prototype[5] = "@5"; 102 assertEquals(array[5], Array.prototype[5]); 103 assertFalse(array.hasOwnProperty(5)); 104 105 assertEquals(array[3], Array.prototype[3]); 106 assertFalse(array.hasOwnProperty(3)); 107 108 assertEquals(array[7], Array.prototype[7]); 109 assertFalse(array.hasOwnProperty(7)); 110 111 assertTrue(delete Array.prototype[3]); 112 assertTrue(delete Array.prototype[5]); 113 assertTrue(delete Array.prototype[7]); 114})(); 115 116// Check that unshift with no args has no side-effects. 117(function() { 118 var len = 3; 119 var array = new Array(len); 120 121 var at0 = '@0'; 122 var at2 = '@2'; 123 124 var array_proto = []; 125 array_proto[0] = at0; 126 array_proto[2] = at2; 127 array.__proto__ = array_proto; 128 129 // array owns nothing... 130 assertFalse(array.hasOwnProperty(0)); 131 assertFalse(array.hasOwnProperty(1)); 132 assertFalse(array.hasOwnProperty(2)); 133 134 // ... but sees values from array_proto. 135 assertEquals(array[0], at0); 136 assertEquals(array[1], undefined); 137 assertEquals(array[2], at2); 138 139 assertEquals(len, array.unshift()); 140 141 // array still owns nothing. 142 assertFalse(array.hasOwnProperty(0)); 143 assertFalse(array.hasOwnProperty(1)); 144 assertFalse(array.hasOwnProperty(2)); 145 146 // ... but still sees values from array_proto. 147 assertEquals(array[0], at0); 148 assertEquals(array[1], undefined); 149 assertEquals(array[2], at2); 150})(); 151 152 153// Now check the case with array of holes and some elements on prototype. 154(function() { 155 var len = 9; 156 var array = new Array(len); 157 var array_proto = [] 158 array_proto[3] = "@3"; 159 array_proto[7] = "@7"; 160 array.__proto__ = array_proto; 161 162 assertEquals(len, array.length); 163 for (var i = 0; i < array.length; i++) { 164 assertEquals(array[i], array_proto[i]); 165 } 166 167 assertEquals(len + 1, array.unshift('head')); 168 169 assertEquals(len + 1, array.length); 170 // Note that unshift copies values from prototype into the array. 171 assertEquals(array[4], array_proto[3]); 172 assertTrue(array.hasOwnProperty(4)); 173 174 assertEquals(array[8], array_proto[7]); 175 assertTrue(array.hasOwnProperty(8)); 176 177 // ... but keeps the rest as holes: 178 array_proto[5] = "@5"; 179 assertEquals(array[5], array_proto[5]); 180 assertFalse(array.hasOwnProperty(5)); 181 182 assertEquals(array[3], array_proto[3]); 183 assertFalse(array.hasOwnProperty(3)); 184 185 assertEquals(array[7], array_proto[7]); 186 assertFalse(array.hasOwnProperty(7)); 187})(); 188 189// Check the behaviour when approaching maximal values for length. 190(function() { 191 for (var i = 0; i < 7; i++) { 192 try { 193 new Array(Math.pow(2, 32) - 3).unshift(1, 2, 3, 4, 5); 194 throw 'Should have thrown RangeError'; 195 } catch (e) { 196 assertTrue(e instanceof RangeError); 197 } 198 199 // Check smi boundary 200 var bigNum = (1 << 30) - 3; 201 assertEquals(bigNum + 7, new Array(bigNum).unshift(1, 2, 3, 4, 5, 6, 7)); 202 } 203})(); 204 205(function() { 206 for (var i = 0; i < 7; i++) { 207 var a = [6, 7, 8, 9]; 208 a.unshift(1, 2, 3, 4, 5); 209 assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], a); 210 } 211})(); 212 213// Check that non-enumerable elements are treated appropriately 214(function() { 215 var array = [2, 3]; 216 Object.defineProperty(array, '1', {enumerable: false}); 217 array.unshift(1) 218 assertEquals([1, 2, 3], array); 219 220 array = [2]; 221 array.length = 2; 222 array.__proto__[1] = 3; 223 Object.defineProperty(array.__proto__, '1', {enumerable: false}); 224 array.unshift(1); 225 assertEquals([1, 2, 3], array); 226})(); 227