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!");