2 * Any copyright is dedicated to the Public Domain.
3 * http://creativecommons.org/licenses/publicdomain/
5 * Jeff Walden <jwalden+code@mit.edu>
8 //-----------------------------------------------------------------------------
9 var BUGNUMBER = 562448;
10 var summary = 'Function.prototype.apply should accept any arraylike arguments';
11 print(BUGNUMBER + ": " + summary);
17 function expectTypeError(fun, msg)
22 assertEq(true, false, "should have thrown a TypeError");
26 assertEq(e instanceof TypeError, true, msg + "; instead threw " + e);
36 var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}];
37 for (var i = 0, sz = nonfuns.length; i < sz; i++)
41 Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]);
44 "expected TypeError calling Function.prototype.apply with uncallable this";
45 expectTypeError(f, msg);
52 var currentThis, currentThisBox;
55 assertEq(arguments.length, 0, "should have been called with no arguments");
56 assertEq(this, currentThis, "wrong this");
58 function strictFunLength()
61 assertEq(arguments.length, 0, "should have been called with no arguments");
62 assertEq(this, currentThis, "wrong this");
67 funLength.apply(undefined);
68 funLength.apply(undefined, undefined);
69 funLength.apply(undefined, null);
71 currentThis = undefined;
72 strictFunLength.apply();
73 strictFunLength.apply(undefined);
74 strictFunLength.apply(undefined, undefined);
75 strictFunLength.apply(undefined, null);
78 strictFunLength.apply(null);
79 strictFunLength.apply(null, undefined);
80 strictFunLength.apply(null, null);
82 currentThis = thisObj;
83 funLength.apply(thisObj);
84 funLength.apply(thisObj, null);
85 funLength.apply(thisObj, undefined);
86 strictFunLength.apply(thisObj);
87 strictFunLength.apply(thisObj, null);
88 strictFunLength.apply(thisObj, undefined);
91 strictFunLength.apply(17);
92 strictFunLength.apply(17, null);
93 strictFunLength.apply(17, undefined);
95 function funThisPrimitive()
97 assertEq(arguments.length, 0, "should have been called with no arguments");
98 assertEq(this instanceof currentThisBox, true,
99 "this not instanceof " + currentThisBox);
100 assertEq(this.valueOf(), currentThis,
101 "wrong this valueOf()");
105 currentThisBox = Number;
106 funThisPrimitive.apply(17);
107 funThisPrimitive.apply(17, undefined);
108 funThisPrimitive.apply(17, null);
110 currentThis = "foopy";
111 currentThisBox = String;
112 funThisPrimitive.apply("foopy");
113 funThisPrimitive.apply("foopy", undefined);
114 funThisPrimitive.apply("foopy", null);
117 currentThisBox = Boolean;
118 funThisPrimitive.apply(false);
119 funThisPrimitive.apply(false, undefined);
120 funThisPrimitive.apply(false, null);
124 var nonobjs = [1, -1, 2.5, "[[Call]]", true, false];
125 for (var i = 0, sz = nonobjs.length; i < sz; i++)
127 var f = function() { fun.apply(thisObj, nonobjs[i]); };
128 var msg = "should have thrown a TypeError with non-object arguments";
129 expectTypeError(f, msg);
134 var args = { get length() { throw 42; } };
137 fun.apply(thisObj, args);
141 assertEq(e, 42, "didn't throw result of [[Get]] on arguments object");
146 * NB: There was an erratum removing the steps numbered 5 and 7 in the original
147 * version of ES5; see also the comments in js_fun_apply.
152 var argsObjectLength =
153 { length: { valueOf: function() { called = true; return 17; } } };
155 fun.apply({}, argsObjectLength);
156 assertEq(called, true, "should have been set in valueOf called via ToUint32");
159 var argsObjectPrimitiveLength =
163 valueOf: function() { upvar = "valueOf"; return {}; },
166 upvar = upvar === "valueOf" ? "both" : "toString";
171 fun.apply({}, argsObjectPrimitiveLength);
172 assertEq(upvar, "both", "didn't call all hooks properly");
176 var seenThis, res, steps;
180 get 0() { steps.push("0"); return 1; },
181 get 1() { steps.push("1"); return 2; },
182 // make sure values shine through holes
183 get 3() { steps.push("3"); return 8; },
186 Object.prototype[2] = 729;
188 seenThis = "not seen";
189 function argsAsArray()
193 return Array.prototype.map.call(arguments, function(v) { return v; });
197 res = argsAsArray.apply(thisObj, argsAccessors);
198 assertEq(seenThis, thisObj, "saw wrong this");
200 assertEq(steps.length, 4, "wrong steps: " + steps);
201 assertEq(steps[0], "0", "bad step 0");
202 assertEq(steps[1], "1", "bad step 1");
203 assertEq(steps[2], "3", "bad step 3");
204 assertEq(steps[3], Math.PI, "bad last step");
206 assertEq(res.length, 4, "wrong return: " + res);
207 assertEq(res[0], 1, "wrong ret[0]");
208 assertEq(res[1], 2, "wrong ret[0]");
209 assertEq(res[2], 729, "wrong ret[0]");
210 assertEq(res[3], 8, "wrong ret[0]");
212 seenThis = "not seen";
213 function strictArgsAsArray()
218 return Array.prototype.map.call(arguments, function(v) { return v; });
222 res = strictArgsAsArray.apply(null, argsAccessors);
223 assertEq(seenThis, null, "saw wrong this");
225 assertEq(steps.length, 4, "wrong steps: " + steps);
226 assertEq(steps[0], "0", "bad step 0");
227 assertEq(steps[1], "1", "bad step 1");
228 assertEq(steps[2], "3", "bad step 3");
229 assertEq(steps[3], 0 / 0, "bad last step");
231 assertEq(res.length, 4, "wrong return: " + res);
232 assertEq(res[0], 1, "wrong ret[0]");
233 assertEq(res[1], 2, "wrong ret[0]");
234 assertEq(res[2], 729, "wrong ret[0]");
235 assertEq(res[3], 8, "wrong ret[0]");
237 strictArgsAsArray.apply(17, argsAccessors);
238 assertEq(seenThis, 17, "saw wrong this");
240 /******************************************************************************/
242 if (typeof reportCompare === "function")
243 reportCompare(true, true);
245 print("All tests passed!");