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 28// Flags: --harmony-arrays 29 30assertEquals(1, Array.prototype.find.length); 31 32var a = [21, 22, 23, 24]; 33assertEquals(undefined, a.find(function() { return false; })); 34assertEquals(21, a.find(function() { return true; })); 35assertEquals(undefined, a.find(function(val) { return 121 === val; })); 36assertEquals(24, a.find(function(val) { return 24 === val; })); 37assertEquals(23, a.find(function(val) { return 23 === val; }), null); 38assertEquals(22, a.find(function(val) { return 22 === val; }), undefined); 39 40 41// 42// Test predicate is not called when array is empty 43// 44(function() { 45 var a = []; 46 var l = -1; 47 var o = -1; 48 var v = -1; 49 var k = -1; 50 51 a.find(function(val, key, obj) { 52 o = obj; 53 l = obj.length; 54 v = val; 55 k = key; 56 57 return false; 58 }); 59 60 assertEquals(-1, l); 61 assertEquals(-1, o); 62 assertEquals(-1, v); 63 assertEquals(-1, k); 64})(); 65 66 67// 68// Test predicate is called with correct argumetns 69// 70(function() { 71 var a = ["b"]; 72 var l = -1; 73 var o = -1; 74 var v = -1; 75 var k = -1; 76 77 var found = a.find(function(val, key, obj) { 78 o = obj; 79 l = obj.length; 80 v = val; 81 k = key; 82 83 return false; 84 }); 85 86 assertArrayEquals(a, o); 87 assertEquals(a.length, l); 88 assertEquals("b", v); 89 assertEquals(0, k); 90 assertEquals(undefined, found); 91})(); 92 93 94// 95// Test predicate is called array.length times 96// 97(function() { 98 var a = [1, 2, 3, 4, 5]; 99 var l = 0; 100 var found = a.find(function() { 101 l++; 102 return false; 103 }); 104 105 assertEquals(a.length, l); 106 assertEquals(undefined, found); 107})(); 108 109 110// 111// Test Array.prototype.find works with String 112// 113(function() { 114 var a = "abcd"; 115 var l = -1; 116 var o = -1; 117 var v = -1; 118 var k = -1; 119 var found = Array.prototype.find.call(a, function(val, key, obj) { 120 o = obj.toString(); 121 l = obj.length; 122 v = val; 123 k = key; 124 125 return false; 126 }); 127 128 assertEquals(a, o); 129 assertEquals(a.length, l); 130 assertEquals("d", v); 131 assertEquals(3, k); 132 assertEquals(undefined, found); 133 134 found = Array.prototype.find.apply(a, [function(val, key, obj) { 135 o = obj.toString(); 136 l = obj.length; 137 v = val; 138 k = key; 139 140 return true; 141 }]); 142 143 assertEquals(a, o); 144 assertEquals(a.length, l); 145 assertEquals("a", v); 146 assertEquals(0, k); 147 assertEquals("a", found); 148})(); 149 150 151// 152// Test Array.prototype.find works with exotic object 153// 154(function() { 155 var l = -1; 156 var o = -1; 157 var v = -1; 158 var k = -1; 159 var a = { 160 prop1: "val1", 161 prop2: "val2", 162 isValid: function() { 163 return this.prop1 === "val1" && this.prop2 === "val2"; 164 } 165 }; 166 167 Array.prototype.push.apply(a, [30, 31, 32]); 168 var found = Array.prototype.find.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(undefined, found); 182})(); 183 184 185// 186// Test array modifications 187// 188(function() { 189 var a = [1, 2, 3]; 190 var found = a.find(function(val) { a.push(val); return false; }); 191 assertArrayEquals([1, 2, 3, 1, 2, 3], a); 192 assertEquals(6, a.length); 193 assertEquals(undefined, found); 194 195 a = [1, 2, 3]; 196 found = a.find(function(val, key) { a[key] = ++val; return false; }); 197 assertArrayEquals([2, 3, 4], a); 198 assertEquals(3, a.length); 199 assertEquals(undefined, found); 200})(); 201 202 203// 204// Test predicate is only called for existing elements 205// 206(function() { 207 var a = new Array(30); 208 a[11] = 21; 209 a[7] = 10; 210 a[29] = 31; 211 212 var count = 0; 213 a.find(function() { count++; return false; }); 214 assertEquals(3, count); 215})(); 216 217 218// 219// Test thisArg 220// 221(function() { 222 // Test String as a thisArg 223 var found = [1, 2, 3].find(function(val, key) { 224 return this.charAt(Number(key)) === String(val); 225 }, "321"); 226 assertEquals(2, found); 227 228 // Test object as a thisArg 229 var thisArg = { 230 elementAt: function(key) { 231 return this[key]; 232 } 233 }; 234 Array.prototype.push.apply(thisArg, ["c", "b", "a"]); 235 236 found = ["a", "b", "c"].find(function(val, key) { 237 return this.elementAt(key) === val; 238 }, thisArg); 239 assertEquals("b", found); 240})(); 241 242// Test exceptions 243assertThrows('Array.prototype.find.call(null, function() { })', 244 TypeError); 245assertThrows('Array.prototype.find.call(undefined, function() { })', 246 TypeError); 247assertThrows('Array.prototype.find.apply(null, function() { }, [])', 248 TypeError); 249assertThrows('Array.prototype.find.apply(undefined, function() { }, [])', 250 TypeError); 251 252assertThrows('[].find(null)', TypeError); 253assertThrows('[].find(undefined)', TypeError); 254assertThrows('[].find(0)', TypeError); 255assertThrows('[].find(true)', TypeError); 256assertThrows('[].find(false)', TypeError); 257assertThrows('[].find("")', TypeError); 258assertThrows('[].find({})', TypeError); 259assertThrows('[].find([])', TypeError); 260assertThrows('[].find(/\d+/)', TypeError); 261 262assertThrows('Array.prototype.find.call({}, null)', TypeError); 263assertThrows('Array.prototype.find.call({}, undefined)', TypeError); 264assertThrows('Array.prototype.find.call({}, 0)', TypeError); 265assertThrows('Array.prototype.find.call({}, true)', TypeError); 266assertThrows('Array.prototype.find.call({}, false)', TypeError); 267assertThrows('Array.prototype.find.call({}, "")', TypeError); 268assertThrows('Array.prototype.find.call({}, {})', TypeError); 269assertThrows('Array.prototype.find.call({}, [])', TypeError); 270assertThrows('Array.prototype.find.call({}, /\d+/)', TypeError); 271 272assertThrows('Array.prototype.find.apply({}, null, [])', TypeError); 273assertThrows('Array.prototype.find.apply({}, undefined, [])', TypeError); 274assertThrows('Array.prototype.find.apply({}, 0, [])', TypeError); 275assertThrows('Array.prototype.find.apply({}, true, [])', TypeError); 276assertThrows('Array.prototype.find.apply({}, false, [])', TypeError); 277assertThrows('Array.prototype.find.apply({}, "", [])', TypeError); 278assertThrows('Array.prototype.find.apply({}, {}, [])', TypeError); 279assertThrows('Array.prototype.find.apply({}, [], [])', TypeError); 280assertThrows('Array.prototype.find.apply({}, /\d+/, [])', TypeError); 281