Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / tests / ecma_5 / Function / 15.3.4.3-01.js
1 /*
2  * Any copyright is dedicated to the Public Domain.
3  * http://creativecommons.org/licenses/publicdomain/
4  * Contributor:
5  *   Jeff Walden <jwalden+code@mit.edu>
6  */
7
8 //-----------------------------------------------------------------------------
9 var BUGNUMBER = 562448;
10 var summary = 'Function.prototype.apply should accept any arraylike arguments';
11 print(BUGNUMBER + ": " + summary);
12
13 /**************
14  * BEGIN TEST *
15  **************/
16
17 function expectTypeError(fun, msg)
18 {
19   try
20   {
21     fun();
22     assertEq(true, false, "should have thrown a TypeError");
23   }
24   catch (e)
25   {
26     assertEq(e instanceof TypeError, true, msg + "; instead threw " + e);
27   }
28 }
29
30 function fun() { }
31
32 var global = this;
33
34
35 /* Step 1. */
36 var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}];
37 for (var i = 0, sz = nonfuns.length; i < sz; i++)
38 {
39   var f = function()
40   {
41     Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]);
42   };
43   var msg =
44     "expected TypeError calling Function.prototype.apply with uncallable this";
45   expectTypeError(f, msg);
46 }
47
48
49 /* Step 2. */
50 var thisObj = {};
51
52 var currentThis, currentThisBox;
53 function funLength()
54 {
55   assertEq(arguments.length, 0, "should have been called with no arguments");
56   assertEq(this, currentThis, "wrong this");
57 }
58 function strictFunLength()
59 {
60   "use strict";
61   assertEq(arguments.length, 0, "should have been called with no arguments");
62   assertEq(this, currentThis, "wrong this");
63 }
64
65 currentThis = global;
66 funLength.apply();
67 funLength.apply(undefined);
68 funLength.apply(undefined, undefined);
69 funLength.apply(undefined, null);
70
71 currentThis = undefined;
72 strictFunLength.apply();
73 strictFunLength.apply(undefined);
74 strictFunLength.apply(undefined, undefined);
75 strictFunLength.apply(undefined, null);
76
77 currentThis = null;
78 strictFunLength.apply(null);
79 strictFunLength.apply(null, undefined);
80 strictFunLength.apply(null, null);
81
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);
89
90 currentThis = 17;
91 strictFunLength.apply(17);
92 strictFunLength.apply(17, null);
93 strictFunLength.apply(17, undefined);
94
95 function funThisPrimitive()
96 {
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()");
102 }
103
104 currentThis = 17;
105 currentThisBox = Number;
106 funThisPrimitive.apply(17);
107 funThisPrimitive.apply(17, undefined);
108 funThisPrimitive.apply(17, null);
109
110 currentThis = "foopy";
111 currentThisBox = String;
112 funThisPrimitive.apply("foopy");
113 funThisPrimitive.apply("foopy", undefined);
114 funThisPrimitive.apply("foopy", null);
115
116 currentThis = false;
117 currentThisBox = Boolean;
118 funThisPrimitive.apply(false);
119 funThisPrimitive.apply(false, undefined);
120 funThisPrimitive.apply(false, null);
121
122
123 /* Step 3. */
124 var nonobjs = [1, -1, 2.5, "[[Call]]", true, false];
125 for (var i = 0, sz = nonobjs.length; i < sz; i++)
126 {
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);
130 }
131
132
133 /* Step 4. */
134 var args = { get length() { throw 42; } };
135 try
136 {
137   fun.apply(thisObj, args);
138 }
139 catch (e)
140 {
141   assertEq(e, 42, "didn't throw result of [[Get]] on arguments object");
142 }
143
144
145 /*
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.
148  */
149
150 /* Step 5. */
151 var called = false;
152 var argsObjectLength =
153   { length: { valueOf: function() { called = true; return 17; } } };
154
155 fun.apply({}, argsObjectLength);
156 assertEq(called, true, "should have been set in valueOf called via ToUint32");
157
158 var upvar = "unset";
159 var argsObjectPrimitiveLength =
160   {
161     length:
162       {
163         valueOf: function() { upvar = "valueOf"; return {}; },
164         toString: function()
165         {
166           upvar = upvar === "valueOf" ? "both" : "toString";
167           return 17;
168         }
169       }
170   };
171 fun.apply({}, argsObjectPrimitiveLength);
172 assertEq(upvar, "both", "didn't call all hooks properly");
173
174
175 /* Step 6-9. */
176 var seenThis, res, steps;
177 var argsAccessors =
178   {
179     length: 4,
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; },
184   };
185
186 Object.prototype[2] = 729;
187
188 seenThis = "not seen";
189 function argsAsArray()
190 {
191   seenThis = this;
192   steps.push(Math.PI);
193   return Array.prototype.map.call(arguments, function(v) { return v; });
194 }
195
196 steps = [];
197 res = argsAsArray.apply(thisObj, argsAccessors);
198 assertEq(seenThis, thisObj, "saw wrong this");
199
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");
205
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]");
211
212 seenThis = "not seen";
213 function strictArgsAsArray()
214 {
215   "use strict";
216   seenThis = this;
217   steps.push(NaN);
218   return Array.prototype.map.call(arguments, function(v) { return v; });
219 }
220
221 steps = [];
222 res = strictArgsAsArray.apply(null, argsAccessors);
223 assertEq(seenThis, null, "saw wrong this");
224
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");
230
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]");
236
237 strictArgsAsArray.apply(17, argsAccessors);
238 assertEq(seenThis, 17, "saw wrong this");
239
240 /******************************************************************************/
241
242 if (typeof reportCompare === "function")
243   reportCompare(true, true);
244
245 print("All tests passed!");