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 24description('Tests to ensure that Function.apply works correctly for Arrays, arguments and array-like objects.'); 25 26function argumentsApply1(a, b, c) 27{ 28 function t(a, b, c) 29 { 30 return a; 31 } 32 return t.apply(null, arguments); 33} 34 35function argumentsApply2(a, b, c) 36{ 37 function t(a, b, c) 38 { 39 return b; 40 } 41 return t.apply(null, arguments); 42} 43 44function argumentsApply3(a, b, c) 45{ 46 function t(a, b, c) 47 { 48 return c; 49 } 50 return t.apply(null, arguments); 51} 52 53function argumentsApplyLength(a, b, c) 54{ 55 function t(a, b, c) 56 { 57 return arguments.length; 58 } 59 return t.apply(null, arguments); 60} 61var executedAdditionalArgument = false; 62function 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 71shouldBe("argumentsApply1(1, 2, 3)", "1"); 72shouldBe("argumentsApply2(1, 2, 3)", "2"); 73shouldBe("argumentsApply3(1, 2, 3)", "3"); 74shouldBe("argumentsApplyLength(1, 2, 3)", "3"); 75shouldBe("argumentsApplyExcessArguments(1, 2, 3)", "3"); 76shouldBeTrue("executedAdditionalArgument"); 77 78function arrayApply1(array) 79{ 80 function t(a, b, c) 81 { 82 return a; 83 } 84 return t.apply(null, array); 85} 86 87function arrayApply2(array) 88{ 89 function t(a, b, c) 90 { 91 return b; 92 } 93 return t.apply(null, array); 94} 95 96function arrayApply3(array) 97{ 98 function t(a, b, c) 99 { 100 return c; 101 } 102 return t.apply(null, array); 103} 104 105function arrayApplyLength(array) 106{ 107 function t(a, b, c) 108 { 109 return arguments.length; 110 } 111 return t.apply(null, array); 112} 113 114shouldBe("arrayApply1([1, 2, 3])", "1"); 115shouldBe("arrayApply2([1, 2, 3])", "2"); 116shouldBe("arrayApply3([1, 2, 3])", "3"); 117shouldBe("arrayApplyLength([1, 2, 3])", "3"); 118 119 120function 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 130function 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 140function 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 150function 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 160shouldBe("argumentsApplyDelete1(1, 2, 3)", "1"); 161shouldBe("argumentsApplyDelete2(1, 2, 3)", "undefined"); 162shouldBe("argumentsApplyDelete3(1, 2, 3)", "3"); 163shouldBe("argumentsApplyDeleteLength(1, 2, 3)", "3"); 164 165 166function 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 176function 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 186function 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 196function 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 206shouldBe("arrayApplyDelete1([1, 2, 3])", "1"); 207shouldBe("arrayApplyDelete2([1, 2, 3])", "undefined"); 208shouldBe("arrayApplyDelete3([1, 2, 3])", "3"); 209shouldBe("arrayApplyDeleteLength([1, 2, 3])", "3"); 210 211 212function argumentsApplyChangeLength1() 213{ 214 function f() { 215 return arguments.length; 216 }; 217 arguments.length = 2; 218 return f.apply(null, arguments); 219} 220 221 222function argumentsApplyChangeLength2() 223{ 224 function f(a) { 225 return arguments.length; 226 }; 227 arguments.length = 2; 228 return f.apply(null, arguments); 229} 230 231 232function 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 241function argumentsApplyChangeLength4() 242{ 243 function f() { 244 return arguments.length; 245 }; 246 arguments.length = 0; 247 return f.apply(null, arguments); 248}; 249 250function argumentsApplyChangeLength5() 251{ 252 function f() { 253 return arguments.length; 254 }; 255 arguments.length = "Not A Number"; 256 return f.apply(null, arguments); 257} 258 259shouldBe("argumentsApplyChangeLength1(1)", "2"); 260shouldBe("argumentsApplyChangeLength2(1)", "2"); 261shouldBe("argumentsApplyChangeLength3(1)", "2"); 262shouldBe("argumentsApplyChangeLength4(1)", "0"); 263shouldBe("argumentsApplyChangeLength5(1)", "0"); 264 265function 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 275function 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 285function 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 295function 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 305shouldBe("arrayApplyChangeLength1()", "2"); 306shouldBe("arrayApplyChangeLength2()", "2"); 307shouldBe("arrayApplyChangeLength3()", "2"); 308shouldBe("arrayApplyChangeLength4()", "0"); 309 310shouldBe("var a = []; a.length = 0xFFFE; [].constructor.apply('', a).length", "0xFFFE"); 311shouldBe("var a = []; a.length = 0xFFFF; [].constructor.apply('', a).length", "0xFFFF"); 312shouldBe("var a = []; a.length = 0x10000; [].constructor.apply('', a).length", "0x10000"); 313shouldBe("var a = []; a.length = 0x10001; [].constructor.apply('', a).length", "0x10001"); 314shouldThrow("var a = []; a.length = 0xFFFFFFFE; [].constructor.apply('', a).length"); 315shouldThrow("var a = []; a.length = 0xFFFFFFFF; [].constructor.apply('', a).length"); 316 317// ES5 permits apply with array-like objects. 318shouldBe("(function(a,b,c,d){ return d ? -1 : (a+b+c); }).apply(undefined, {length:3, 0:100, 1:20, 2:3})", '123'); 319