1// Copyright 2013 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 28assertEquals(1, Array.prototype.findIndex.length); 29 30var a = [21, 22, 23, 24]; 31assertEquals(-1, a.findIndex(function() { return false; })); 32assertEquals(-1, a.findIndex(function(val) { return 121 === val; })); 33assertEquals(0, a.findIndex(function() { return true; })); 34assertEquals(1, a.findIndex(function(val) { return 22 === val; }), undefined); 35assertEquals(2, a.findIndex(function(val) { return 23 === val; }), null); 36assertEquals(3, a.findIndex(function(val) { return 24 === val; })); 37 38 39// 40// Test predicate is not called when array is empty 41// 42(function() { 43 var a = []; 44 var l = -1; 45 var o = -1; 46 var v = -1; 47 var k = -1; 48 49 a.findIndex(function(val, key, obj) { 50 o = obj; 51 l = obj.length; 52 v = val; 53 k = key; 54 55 return false; 56 }); 57 58 assertEquals(-1, l); 59 assertEquals(-1, o); 60 assertEquals(-1, v); 61 assertEquals(-1, k); 62})(); 63 64 65// 66// Test predicate is called with correct argumetns 67// 68(function() { 69 var a = ["b"]; 70 var l = -1; 71 var o = -1; 72 var v = -1; 73 var k = -1; 74 75 var index = a.findIndex(function(val, key, obj) { 76 o = obj; 77 l = obj.length; 78 v = val; 79 k = key; 80 81 return false; 82 }); 83 84 assertArrayEquals(a, o); 85 assertEquals(a.length, l); 86 assertEquals("b", v); 87 assertEquals(0, k); 88 assertEquals(-1, index); 89})(); 90 91 92// 93// Test predicate is called array.length times 94// 95(function() { 96 var a = [1, 2, 3, 4, 5]; 97 var l = 0; 98 99 a.findIndex(function() { 100 l++; 101 return false; 102 }); 103 104 assertEquals(a.length, l); 105})(); 106 107 108// 109// Test Array.prototype.findIndex works with String 110// 111(function() { 112 var a = "abcd"; 113 var l = -1; 114 var o = -1; 115 var v = -1; 116 var k = -1; 117 118 var index = Array.prototype.findIndex.call(a, function(val, key, obj) { 119 o = obj.toString(); 120 l = obj.length; 121 v = val; 122 k = key; 123 124 return false; 125 }); 126 127 assertEquals(a, o); 128 assertEquals(a.length, l); 129 assertEquals("d", v); 130 assertEquals(3, k); 131 assertEquals(-1, index); 132 133 index = Array.prototype.findIndex.apply(a, [function(val, key, obj) { 134 o = obj.toString(); 135 l = obj.length; 136 v = val; 137 k = key; 138 139 return true; 140 }]); 141 142 assertEquals(a, o); 143 assertEquals(a.length, l); 144 assertEquals("a", v); 145 assertEquals(0, k); 146 assertEquals(0, index); 147})(); 148 149 150// 151// Test Array.prototype.findIndex works with exotic object 152// 153(function() { 154 var l = -1; 155 var o = -1; 156 var v = -1; 157 var k = -1; 158 var a = { 159 prop1: "val1", 160 prop2: "val2", 161 isValid: function() { 162 return this.prop1 === "val1" && this.prop2 === "val2"; 163 } 164 }; 165 166 Array.prototype.push.apply(a, [30, 31, 32]); 167 168 var index = Array.prototype.findIndex.call(a, function(val, key, obj) { 169 o = obj; 170 l = obj.length; 171 v = val; 172 k = key; 173 174 return !obj.isValid(); 175 }); 176 177 assertArrayEquals(a, o); 178 assertEquals(3, l); 179 assertEquals(32, v); 180 assertEquals(2, k); 181 assertEquals(-1, index); 182})(); 183 184 185// 186// Test array modifications 187// 188(function() { 189 var a = [1, 2, 3]; 190 a.findIndex(function(val) { a.push(val); return false; }); 191 assertArrayEquals([1, 2, 3, 1, 2, 3], a); 192 assertEquals(6, a.length); 193 194 a = [1, 2, 3]; 195 a.findIndex(function(val, key) { a[key] = ++val; return false; }); 196 assertArrayEquals([2, 3, 4], a); 197 assertEquals(3, a.length); 198})(); 199 200 201// 202// Test predicate is called for holes 203// 204(function() { 205 var a = new Array(30); 206 a[11] = 21; 207 a[7] = 10; 208 a[29] = 31; 209 210 var count = 0; 211 a.findIndex(function() { count++; return false; }); 212 assertEquals(30, count); 213})(); 214 215 216(function() { 217 var a = [0, 1, , 3]; 218 var count = 0; 219 var index = a.findIndex(function(val) { return val === undefined; }); 220 assertEquals(2, index); 221})(); 222 223 224(function() { 225 var a = [0, 1, , 3]; 226 a.__proto__ = { 227 __proto__: Array.prototype, 228 2: 42, 229 }; 230 var count = 0; 231 var index = a.findIndex(function(val) { return val === 42; }); 232 assertEquals(2, index); 233})(); 234 235 236// 237// Test thisArg 238// 239(function() { 240 // Test String as a thisArg 241 var index = [1, 2, 3].findIndex(function(val, key) { 242 return this.charAt(Number(key)) === String(val); 243 }, "321"); 244 assertEquals(1, index); 245 246 // Test object as a thisArg 247 var thisArg = { 248 elementAt: function(key) { 249 return this[key]; 250 } 251 }; 252 Array.prototype.push.apply(thisArg, ["c", "b", "a"]); 253 254 index = ["a", "b", "c"].findIndex(function(val, key) { 255 return this.elementAt(key) === val; 256 }, thisArg); 257 assertEquals(1, index); 258 259 // Create a new object in each function call when receiver is a 260 // primitive value. See ECMA-262, Annex C. 261 a = []; 262 [1, 2].findIndex(function() { a.push(this) }, ""); 263 assertTrue(a[0] !== a[1]); 264 265 // Do not create a new object otherwise. 266 a = []; 267 [1, 2].findIndex(function() { a.push(this) }, {}); 268 assertEquals(a[0], a[1]); 269 270 // In strict mode primitive values should not be coerced to an object. 271 a = []; 272 [1, 2].findIndex(function() { 'use strict'; a.push(this); }, ""); 273 assertEquals("", a[0]); 274 assertEquals(a[0], a[1]); 275 276})(); 277 278// Test exceptions 279assertThrows('Array.prototype.findIndex.call(null, function() { })', 280 TypeError); 281assertThrows('Array.prototype.findIndex.call(undefined, function() { })', 282 TypeError); 283assertThrows('Array.prototype.findIndex.apply(null, function() { }, [])', 284 TypeError); 285assertThrows('Array.prototype.findIndex.apply(undefined, function() { }, [])', 286 TypeError); 287 288assertThrows('[].findIndex(null)', TypeError); 289assertThrows('[].findIndex(undefined)', TypeError); 290assertThrows('[].findIndex(0)', TypeError); 291assertThrows('[].findIndex(true)', TypeError); 292assertThrows('[].findIndex(false)', TypeError); 293assertThrows('[].findIndex("")', TypeError); 294assertThrows('[].findIndex({})', TypeError); 295assertThrows('[].findIndex([])', TypeError); 296assertThrows('[].findIndex(/\d+/)', TypeError); 297 298assertThrows('Array.prototype.findIndex.call({}, null)', TypeError); 299assertThrows('Array.prototype.findIndex.call({}, undefined)', TypeError); 300assertThrows('Array.prototype.findIndex.call({}, 0)', TypeError); 301assertThrows('Array.prototype.findIndex.call({}, true)', TypeError); 302assertThrows('Array.prototype.findIndex.call({}, false)', TypeError); 303assertThrows('Array.prototype.findIndex.call({}, "")', TypeError); 304assertThrows('Array.prototype.findIndex.call({}, {})', TypeError); 305assertThrows('Array.prototype.findIndex.call({}, [])', TypeError); 306assertThrows('Array.prototype.findIndex.call({}, /\d+/)', TypeError); 307 308assertThrows('Array.prototype.findIndex.apply({}, null, [])', TypeError); 309assertThrows('Array.prototype.findIndex.apply({}, undefined, [])', TypeError); 310assertThrows('Array.prototype.findIndex.apply({}, 0, [])', TypeError); 311assertThrows('Array.prototype.findIndex.apply({}, true, [])', TypeError); 312assertThrows('Array.prototype.findIndex.apply({}, false, [])', TypeError); 313assertThrows('Array.prototype.findIndex.apply({}, "", [])', TypeError); 314assertThrows('Array.prototype.findIndex.apply({}, {}, [])', TypeError); 315assertThrows('Array.prototype.findIndex.apply({}, [], [])', TypeError); 316assertThrows('Array.prototype.findIndex.apply({}, /\d+/, [])', TypeError); 317