1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_5/Function/15.3.4.3-01.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +/* 1.5 + * Any copyright is dedicated to the Public Domain. 1.6 + * http://creativecommons.org/licenses/publicdomain/ 1.7 + * Contributor: 1.8 + * Jeff Walden <jwalden+code@mit.edu> 1.9 + */ 1.10 + 1.11 +//----------------------------------------------------------------------------- 1.12 +var BUGNUMBER = 562448; 1.13 +var summary = 'Function.prototype.apply should accept any arraylike arguments'; 1.14 +print(BUGNUMBER + ": " + summary); 1.15 + 1.16 +/************** 1.17 + * BEGIN TEST * 1.18 + **************/ 1.19 + 1.20 +function expectTypeError(fun, msg) 1.21 +{ 1.22 + try 1.23 + { 1.24 + fun(); 1.25 + assertEq(true, false, "should have thrown a TypeError"); 1.26 + } 1.27 + catch (e) 1.28 + { 1.29 + assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); 1.30 + } 1.31 +} 1.32 + 1.33 +function fun() { } 1.34 + 1.35 +var global = this; 1.36 + 1.37 + 1.38 +/* Step 1. */ 1.39 +var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; 1.40 +for (var i = 0, sz = nonfuns.length; i < sz; i++) 1.41 +{ 1.42 + var f = function() 1.43 + { 1.44 + Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]); 1.45 + }; 1.46 + var msg = 1.47 + "expected TypeError calling Function.prototype.apply with uncallable this"; 1.48 + expectTypeError(f, msg); 1.49 +} 1.50 + 1.51 + 1.52 +/* Step 2. */ 1.53 +var thisObj = {}; 1.54 + 1.55 +var currentThis, currentThisBox; 1.56 +function funLength() 1.57 +{ 1.58 + assertEq(arguments.length, 0, "should have been called with no arguments"); 1.59 + assertEq(this, currentThis, "wrong this"); 1.60 +} 1.61 +function strictFunLength() 1.62 +{ 1.63 + "use strict"; 1.64 + assertEq(arguments.length, 0, "should have been called with no arguments"); 1.65 + assertEq(this, currentThis, "wrong this"); 1.66 +} 1.67 + 1.68 +currentThis = global; 1.69 +funLength.apply(); 1.70 +funLength.apply(undefined); 1.71 +funLength.apply(undefined, undefined); 1.72 +funLength.apply(undefined, null); 1.73 + 1.74 +currentThis = undefined; 1.75 +strictFunLength.apply(); 1.76 +strictFunLength.apply(undefined); 1.77 +strictFunLength.apply(undefined, undefined); 1.78 +strictFunLength.apply(undefined, null); 1.79 + 1.80 +currentThis = null; 1.81 +strictFunLength.apply(null); 1.82 +strictFunLength.apply(null, undefined); 1.83 +strictFunLength.apply(null, null); 1.84 + 1.85 +currentThis = thisObj; 1.86 +funLength.apply(thisObj); 1.87 +funLength.apply(thisObj, null); 1.88 +funLength.apply(thisObj, undefined); 1.89 +strictFunLength.apply(thisObj); 1.90 +strictFunLength.apply(thisObj, null); 1.91 +strictFunLength.apply(thisObj, undefined); 1.92 + 1.93 +currentThis = 17; 1.94 +strictFunLength.apply(17); 1.95 +strictFunLength.apply(17, null); 1.96 +strictFunLength.apply(17, undefined); 1.97 + 1.98 +function funThisPrimitive() 1.99 +{ 1.100 + assertEq(arguments.length, 0, "should have been called with no arguments"); 1.101 + assertEq(this instanceof currentThisBox, true, 1.102 + "this not instanceof " + currentThisBox); 1.103 + assertEq(this.valueOf(), currentThis, 1.104 + "wrong this valueOf()"); 1.105 +} 1.106 + 1.107 +currentThis = 17; 1.108 +currentThisBox = Number; 1.109 +funThisPrimitive.apply(17); 1.110 +funThisPrimitive.apply(17, undefined); 1.111 +funThisPrimitive.apply(17, null); 1.112 + 1.113 +currentThis = "foopy"; 1.114 +currentThisBox = String; 1.115 +funThisPrimitive.apply("foopy"); 1.116 +funThisPrimitive.apply("foopy", undefined); 1.117 +funThisPrimitive.apply("foopy", null); 1.118 + 1.119 +currentThis = false; 1.120 +currentThisBox = Boolean; 1.121 +funThisPrimitive.apply(false); 1.122 +funThisPrimitive.apply(false, undefined); 1.123 +funThisPrimitive.apply(false, null); 1.124 + 1.125 + 1.126 +/* Step 3. */ 1.127 +var nonobjs = [1, -1, 2.5, "[[Call]]", true, false]; 1.128 +for (var i = 0, sz = nonobjs.length; i < sz; i++) 1.129 +{ 1.130 + var f = function() { fun.apply(thisObj, nonobjs[i]); }; 1.131 + var msg = "should have thrown a TypeError with non-object arguments"; 1.132 + expectTypeError(f, msg); 1.133 +} 1.134 + 1.135 + 1.136 +/* Step 4. */ 1.137 +var args = { get length() { throw 42; } }; 1.138 +try 1.139 +{ 1.140 + fun.apply(thisObj, args); 1.141 +} 1.142 +catch (e) 1.143 +{ 1.144 + assertEq(e, 42, "didn't throw result of [[Get]] on arguments object"); 1.145 +} 1.146 + 1.147 + 1.148 +/* 1.149 + * NB: There was an erratum removing the steps numbered 5 and 7 in the original 1.150 + * version of ES5; see also the comments in js_fun_apply. 1.151 + */ 1.152 + 1.153 +/* Step 5. */ 1.154 +var called = false; 1.155 +var argsObjectLength = 1.156 + { length: { valueOf: function() { called = true; return 17; } } }; 1.157 + 1.158 +fun.apply({}, argsObjectLength); 1.159 +assertEq(called, true, "should have been set in valueOf called via ToUint32"); 1.160 + 1.161 +var upvar = "unset"; 1.162 +var argsObjectPrimitiveLength = 1.163 + { 1.164 + length: 1.165 + { 1.166 + valueOf: function() { upvar = "valueOf"; return {}; }, 1.167 + toString: function() 1.168 + { 1.169 + upvar = upvar === "valueOf" ? "both" : "toString"; 1.170 + return 17; 1.171 + } 1.172 + } 1.173 + }; 1.174 +fun.apply({}, argsObjectPrimitiveLength); 1.175 +assertEq(upvar, "both", "didn't call all hooks properly"); 1.176 + 1.177 + 1.178 +/* Step 6-9. */ 1.179 +var seenThis, res, steps; 1.180 +var argsAccessors = 1.181 + { 1.182 + length: 4, 1.183 + get 0() { steps.push("0"); return 1; }, 1.184 + get 1() { steps.push("1"); return 2; }, 1.185 + // make sure values shine through holes 1.186 + get 3() { steps.push("3"); return 8; }, 1.187 + }; 1.188 + 1.189 +Object.prototype[2] = 729; 1.190 + 1.191 +seenThis = "not seen"; 1.192 +function argsAsArray() 1.193 +{ 1.194 + seenThis = this; 1.195 + steps.push(Math.PI); 1.196 + return Array.prototype.map.call(arguments, function(v) { return v; }); 1.197 +} 1.198 + 1.199 +steps = []; 1.200 +res = argsAsArray.apply(thisObj, argsAccessors); 1.201 +assertEq(seenThis, thisObj, "saw wrong this"); 1.202 + 1.203 +assertEq(steps.length, 4, "wrong steps: " + steps); 1.204 +assertEq(steps[0], "0", "bad step 0"); 1.205 +assertEq(steps[1], "1", "bad step 1"); 1.206 +assertEq(steps[2], "3", "bad step 3"); 1.207 +assertEq(steps[3], Math.PI, "bad last step"); 1.208 + 1.209 +assertEq(res.length, 4, "wrong return: " + res); 1.210 +assertEq(res[0], 1, "wrong ret[0]"); 1.211 +assertEq(res[1], 2, "wrong ret[0]"); 1.212 +assertEq(res[2], 729, "wrong ret[0]"); 1.213 +assertEq(res[3], 8, "wrong ret[0]"); 1.214 + 1.215 +seenThis = "not seen"; 1.216 +function strictArgsAsArray() 1.217 +{ 1.218 + "use strict"; 1.219 + seenThis = this; 1.220 + steps.push(NaN); 1.221 + return Array.prototype.map.call(arguments, function(v) { return v; }); 1.222 +} 1.223 + 1.224 +steps = []; 1.225 +res = strictArgsAsArray.apply(null, argsAccessors); 1.226 +assertEq(seenThis, null, "saw wrong this"); 1.227 + 1.228 +assertEq(steps.length, 4, "wrong steps: " + steps); 1.229 +assertEq(steps[0], "0", "bad step 0"); 1.230 +assertEq(steps[1], "1", "bad step 1"); 1.231 +assertEq(steps[2], "3", "bad step 3"); 1.232 +assertEq(steps[3], 0 / 0, "bad last step"); 1.233 + 1.234 +assertEq(res.length, 4, "wrong return: " + res); 1.235 +assertEq(res[0], 1, "wrong ret[0]"); 1.236 +assertEq(res[1], 2, "wrong ret[0]"); 1.237 +assertEq(res[2], 729, "wrong ret[0]"); 1.238 +assertEq(res[3], 8, "wrong ret[0]"); 1.239 + 1.240 +strictArgsAsArray.apply(17, argsAccessors); 1.241 +assertEq(seenThis, 17, "saw wrong this"); 1.242 + 1.243 +/******************************************************************************/ 1.244 + 1.245 +if (typeof reportCompare === "function") 1.246 + reportCompare(true, true); 1.247 + 1.248 +print("All tests passed!");