1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 1. Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // 2. Redistributions in binary form must reproduce the above copyright 10 // notice, this list of conditions and the following disclaimer in the 11 // documentation and/or other materials provided with the distribution. 12 // 13 // THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 // DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24 description('Tests to ensure that Function.apply works correctly for Arrays, arguments and array-like objects.'); 25 26 function argumentsApply1(a, b, c) 27 { 28 function t(a, b, c) 29 { 30 return a; 31 } 32 return t.apply(null, arguments); 33 } 34 35 function argumentsApply2(a, b, c) 36 { 37 function t(a, b, c) 38 { 39 return b; 40 } 41 return t.apply(null, arguments); 42 } 43 44 function argumentsApply3(a, b, c) 45 { 46 function t(a, b, c) 47 { 48 return c; 49 } 50 return t.apply(null, arguments); 51 } 52 53 function argumentsApplyLength(a, b, c) 54 { 55 function t(a, b, c) 56 { 57 return arguments.length; 58 } 59 return t.apply(null, arguments); 60 } 61 var executedAdditionalArgument = false; 62 function argumentsApplyExcessArguments(a, b, c) 63 { 64 function t(a, b, c) 65 { 66 return arguments.length; 67 } 68 return t.apply(null, arguments, executedAdditionalArgument = true); 69 } 70 71 shouldBe("argumentsApply1(1, 2, 3)", "1"); 72 shouldBe("argumentsApply2(1, 2, 3)", "2"); 73 shouldBe("argumentsApply3(1, 2, 3)", "3"); 74 shouldBe("argumentsApplyLength(1, 2, 3)", "3"); 75 shouldBe("argumentsApplyExcessArguments(1, 2, 3)", "3"); 76 shouldBeTrue("executedAdditionalArgument"); 77 78 function arrayApply1(array) 79 { 80 function t(a, b, c) 81 { 82 return a; 83 } 84 return t.apply(null, array); 85 } 86 87 function arrayApply2(array) 88 { 89 function t(a, b, c) 90 { 91 return b; 92 } 93 return t.apply(null, array); 94 } 95 96 function arrayApply3(array) 97 { 98 function t(a, b, c) 99 { 100 return c; 101 } 102 return t.apply(null, array); 103 } 104 105 function arrayApplyLength(array) 106 { 107 function t(a, b, c) 108 { 109 return arguments.length; 110 } 111 return t.apply(null, array); 112 } 113 114 shouldBe("arrayApply1([1, 2, 3])", "1"); 115 shouldBe("arrayApply2([1, 2, 3])", "2"); 116 shouldBe("arrayApply3([1, 2, 3])", "3"); 117 shouldBe("arrayApplyLength([1, 2, 3])", "3"); 118 119 120 function argumentsApplyDelete1(a, b, c) 121 { 122 function t(a, b, c) 123 { 124 return a; 125 } 126 delete arguments[1]; 127 return t.apply(null, arguments); 128 } 129 130 function argumentsApplyDelete2(a, b, c) 131 { 132 function t(a, b, c) 133 { 134 return b; 135 } 136 delete arguments[1]; 137 return t.apply(null, arguments); 138 } 139 140 function argumentsApplyDelete3(a, b, c) 141 { 142 function t(a, b, c) 143 { 144 return c; 145 } 146 delete arguments[1]; 147 return t.apply(null, arguments); 148 } 149 150 function argumentsApplyDeleteLength(a, b, c) 151 { 152 function t(a, b, c) 153 { 154 return arguments.length; 155 } 156 delete arguments[1]; 157 return t.apply(null, arguments); 158 } 159 160 shouldBe("argumentsApplyDelete1(1, 2, 3)", "1"); 161 shouldBe("argumentsApplyDelete2(1, 2, 3)", "undefined"); 162 shouldBe("argumentsApplyDelete3(1, 2, 3)", "3"); 163 shouldBe("argumentsApplyDeleteLength(1, 2, 3)", "3"); 164 165 166 function arrayApplyDelete1(array) 167 { 168 function t(a, b, c) 169 { 170 return a; 171 } 172 delete array[1]; 173 return t.apply(null, array); 174 } 175 176 function arrayApplyDelete2(array) 177 { 178 function t(a, b, c) 179 { 180 return b; 181 } 182 delete array[1]; 183 return t.apply(null, array); 184 } 185 186 function arrayApplyDelete3(array) 187 { 188 function t(a, b, c) 189 { 190 return c; 191 } 192 delete array[1]; 193 return t.apply(null, array); 194 } 195 196 function arrayApplyDeleteLength(array) 197 { 198 function t(a, b, c) 199 { 200 return arguments.length; 201 } 202 delete array[1]; 203 return t.apply(null, array); 204 } 205 206 shouldBe("arrayApplyDelete1([1, 2, 3])", "1"); 207 shouldBe("arrayApplyDelete2([1, 2, 3])", "undefined"); 208 shouldBe("arrayApplyDelete3([1, 2, 3])", "3"); 209 shouldBe("arrayApplyDeleteLength([1, 2, 3])", "3"); 210 211 212 function argumentsApplyChangeLength1() 213 { 214 function f() { 215 return arguments.length; 216 }; 217 arguments.length = 2; 218 return f.apply(null, arguments); 219 } 220 221 222 function argumentsApplyChangeLength2() 223 { 224 function f(a) { 225 return arguments.length; 226 }; 227 arguments.length = 2; 228 return f.apply(null, arguments); 229 } 230 231 232 function argumentsApplyChangeLength3() 233 { 234 function f(a, b, c) { 235 return arguments.length; 236 }; 237 arguments.length = 2; 238 return f.apply(null, arguments); 239 }; 240 241 function argumentsApplyChangeLength4() 242 { 243 function f() { 244 return arguments.length; 245 }; 246 arguments.length = 0; 247 return f.apply(null, arguments); 248 }; 249 250 function argumentsApplyChangeLength5() 251 { 252 function f() { 253 return arguments.length; 254 }; 255 arguments.length = "Not A Number"; 256 return f.apply(null, arguments); 257 } 258 259 shouldBe("argumentsApplyChangeLength1(1)", "2"); 260 shouldBe("argumentsApplyChangeLength2(1)", "2"); 261 shouldBe("argumentsApplyChangeLength3(1)", "2"); 262 shouldBe("argumentsApplyChangeLength4(1)", "0"); 263 shouldBe("argumentsApplyChangeLength5(1)", "0"); 264 265 function arrayApplyChangeLength1() 266 { 267 function f() { 268 return arguments.length; 269 }; 270 var array = []; 271 array.length = 2; 272 return f.apply(null, array); 273 } 274 275 function arrayApplyChangeLength2() 276 { 277 function f(a) { 278 return arguments.length; 279 }; 280 var array = []; 281 array.length = 2; 282 return f.apply(null, array); 283 } 284 285 function arrayApplyChangeLength3() 286 { 287 function f(a, b, c) { 288 return arguments.length; 289 }; 290 var array = []; 291 array.length = 2; 292 return f.apply(null, array); 293 } 294 295 function arrayApplyChangeLength4() 296 { 297 function f() { 298 return arguments.length; 299 }; 300 var array = [1]; 301 array.length = 0; 302 return f.apply(null, array); 303 }; 304 305 shouldBe("arrayApplyChangeLength1()", "2"); 306 shouldBe("arrayApplyChangeLength2()", "2"); 307 shouldBe("arrayApplyChangeLength3()", "2"); 308 shouldBe("arrayApplyChangeLength4()", "0"); 309 310 shouldBe("var a = []; a.length = 0xFFFE; [].constructor.apply('', a).length", "0xFFFE"); 311 shouldBe("var a = []; a.length = 0xFFFF; [].constructor.apply('', a).length", "0xFFFF"); 312 shouldBe("var a = []; a.length = 0x10000; [].constructor.apply('', a).length", "0x10000"); 313 shouldThrow("var a = []; a.length = 0x10001; [].constructor.apply('', a).length"); 314 shouldThrow("var a = []; a.length = 0xFFFFFFFE; [].constructor.apply('', a).length"); 315 shouldThrow("var a = []; a.length = 0xFFFFFFFF; [].constructor.apply('', a).length"); 316 317 // ES5 permits apply with array-like objects. 318 shouldBe("(function(a,b,c,d){ return d ? -1 : (a+b+c); }).apply(undefined, {length:3, 0:100, 1:20, 2:3})", '123'); 319