|
1 // Any copyright is dedicated to the Public Domain. |
|
2 // http://creativecommons.org/licenses/publicdomain/ |
|
3 |
|
4 var gTestfile = 'toJSON-01.js'; |
|
5 //----------------------------------------------------------------------------- |
|
6 var BUGNUMBER = 584811; |
|
7 var summary = "Date.prototype.toJSON isn't to spec"; |
|
8 |
|
9 print(BUGNUMBER + ": " + summary); |
|
10 |
|
11 /************** |
|
12 * BEGIN TEST * |
|
13 **************/ |
|
14 |
|
15 var called; |
|
16 |
|
17 var dateToJSON = Date.prototype.toJSON; |
|
18 assertEq(Date.prototype.hasOwnProperty("toJSON"), true); |
|
19 assertEq(typeof dateToJSON, "function"); |
|
20 |
|
21 // brief test to exercise this outside of isolation, just for sanity |
|
22 var invalidDate = new Date(); |
|
23 invalidDate.setTime(NaN); |
|
24 assertEq(JSON.stringify({ p: invalidDate }), '{"p":null}'); |
|
25 |
|
26 |
|
27 /* 15.9.5.44 Date.prototype.toJSON ( key ) */ |
|
28 assertEq(dateToJSON.length, 1); |
|
29 |
|
30 /* |
|
31 * 1. Let O be the result of calling ToObject, giving it the this value as its |
|
32 * argument. |
|
33 */ |
|
34 try |
|
35 { |
|
36 dateToJSON.call(null); |
|
37 throw new Error("should have thrown a TypeError"); |
|
38 } |
|
39 catch (e) |
|
40 { |
|
41 assertEq(e instanceof TypeError, true, |
|
42 "ToObject throws TypeError for null/undefined"); |
|
43 } |
|
44 |
|
45 try |
|
46 { |
|
47 dateToJSON.call(undefined); |
|
48 throw new Error("should have thrown a TypeError"); |
|
49 } |
|
50 catch (e) |
|
51 { |
|
52 assertEq(e instanceof TypeError, true, |
|
53 "ToObject throws TypeError for null/undefined"); |
|
54 } |
|
55 |
|
56 |
|
57 /* |
|
58 * 2. Let tv be ToPrimitive(O, hint Number). |
|
59 * ...expands to: |
|
60 * 1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf". |
|
61 * 2. If IsCallable(valueOf) is true then, |
|
62 * a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and |
|
63 * an empty argument list. |
|
64 * b. If val is a primitive value, return val. |
|
65 * 3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString". |
|
66 * 4. If IsCallable(toString) is true then, |
|
67 * a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and |
|
68 * an empty argument list. |
|
69 * b. If str is a primitive value, return str. |
|
70 * 5. Throw a TypeError exception. |
|
71 */ |
|
72 try |
|
73 { |
|
74 var r = dateToJSON.call({ get valueOf() { throw 17; } }); |
|
75 throw new Error("didn't throw, returned: " + r); |
|
76 } |
|
77 catch (e) |
|
78 { |
|
79 assertEq(e, 17, "bad exception: " + e); |
|
80 } |
|
81 |
|
82 called = false; |
|
83 assertEq(dateToJSON.call({ valueOf: null, |
|
84 toString: function() { called = true; return 12; }, |
|
85 toISOString: function() { return "ohai"; } }), |
|
86 "ohai"); |
|
87 assertEq(called, true); |
|
88 |
|
89 called = false; |
|
90 assertEq(dateToJSON.call({ valueOf: function() { called = true; return 42; }, |
|
91 toISOString: function() { return null; } }), |
|
92 null); |
|
93 assertEq(called, true); |
|
94 |
|
95 try |
|
96 { |
|
97 called = false; |
|
98 dateToJSON.call({ valueOf: function() { called = true; return {}; }, |
|
99 get toString() { throw 42; } }); |
|
100 } |
|
101 catch (e) |
|
102 { |
|
103 assertEq(called, true); |
|
104 assertEq(e, 42, "bad exception: " + e); |
|
105 } |
|
106 |
|
107 called = false; |
|
108 assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, |
|
109 get toString() { return function() { return 8675309; }; }, |
|
110 toISOString: function() { return true; } }), |
|
111 true); |
|
112 assertEq(called, true); |
|
113 |
|
114 var asserted = false; |
|
115 called = false; |
|
116 assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, |
|
117 get toString() |
|
118 { |
|
119 assertEq(called, true); |
|
120 asserted = true; |
|
121 return function() { return 8675309; }; |
|
122 }, |
|
123 toISOString: function() { return NaN; } }), |
|
124 NaN); |
|
125 assertEq(asserted, true); |
|
126 |
|
127 try |
|
128 { |
|
129 var r = dateToJSON.call({ valueOf: null, toString: null, |
|
130 get toISOString() |
|
131 { |
|
132 throw new Error("shouldn't have been gotten"); |
|
133 } }); |
|
134 throw new Error("didn't throw, returned: " + r); |
|
135 } |
|
136 catch (e) |
|
137 { |
|
138 assertEq(e instanceof TypeError, true, "bad exception: " + e); |
|
139 } |
|
140 |
|
141 |
|
142 /* 3. If tv is a Number and is not finite, return null. */ |
|
143 assertEq(dateToJSON.call({ valueOf: function() { return Infinity; } }), null); |
|
144 assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; } }), null); |
|
145 assertEq(dateToJSON.call({ valueOf: function() { return NaN; } }), null); |
|
146 |
|
147 assertEq(dateToJSON.call({ valueOf: function() { return Infinity; }, |
|
148 toISOString: function() { return {}; } }), null); |
|
149 assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; }, |
|
150 toISOString: function() { return []; } }), null); |
|
151 assertEq(dateToJSON.call({ valueOf: function() { return NaN; }, |
|
152 toISOString: function() { return undefined; } }), null); |
|
153 |
|
154 |
|
155 /* |
|
156 * 4. Let toISO be the result of calling the [[Get]] internal method of O with |
|
157 * argument "toISOString". |
|
158 */ |
|
159 try |
|
160 { |
|
161 var r = dateToJSON.call({ get toISOString() { throw 42; } }); |
|
162 throw new Error("didn't throw, returned: " + r); |
|
163 } |
|
164 catch (e) |
|
165 { |
|
166 assertEq(e, 42, "bad exception: " + e); |
|
167 } |
|
168 |
|
169 |
|
170 /* 5. If IsCallable(toISO) is false, throw a TypeError exception. */ |
|
171 try |
|
172 { |
|
173 var r = dateToJSON.call({ toISOString: null }); |
|
174 throw new Error("didn't throw, returned: " + r); |
|
175 } |
|
176 catch (e) |
|
177 { |
|
178 assertEq(e instanceof TypeError, true, "bad exception: " + e); |
|
179 } |
|
180 |
|
181 try |
|
182 { |
|
183 var r = dateToJSON.call({ toISOString: undefined }); |
|
184 throw new Error("didn't throw, returned: " + r); |
|
185 } |
|
186 catch (e) |
|
187 { |
|
188 assertEq(e instanceof TypeError, true, "bad exception: " + e); |
|
189 } |
|
190 |
|
191 try |
|
192 { |
|
193 var r = dateToJSON.call({ toISOString: "oogabooga" }); |
|
194 throw new Error("didn't throw, returned: " + r); |
|
195 } |
|
196 catch (e) |
|
197 { |
|
198 assertEq(e instanceof TypeError, true, "bad exception: " + e); |
|
199 } |
|
200 |
|
201 try |
|
202 { |
|
203 var r = dateToJSON.call({ toISOString: Math.PI }); |
|
204 throw new Error("didn't throw, returned: " + r); |
|
205 } |
|
206 catch (e) |
|
207 { |
|
208 assertEq(e instanceof TypeError, true, "bad exception: " + e); |
|
209 } |
|
210 |
|
211 |
|
212 /* |
|
213 * 6. Return the result of calling the [[Call]] internal method of toISO with O |
|
214 * as the this value and an empty argument list. |
|
215 */ |
|
216 var o = |
|
217 { |
|
218 toISOString: function(a) |
|
219 { |
|
220 called = true; |
|
221 assertEq(this, o); |
|
222 assertEq(a, undefined); |
|
223 assertEq(arguments.length, 0); |
|
224 return obj; |
|
225 } |
|
226 }; |
|
227 var obj = {}; |
|
228 called = false; |
|
229 assertEq(dateToJSON.call(o), obj, "should have gotten obj back"); |
|
230 assertEq(called, true); |
|
231 |
|
232 |
|
233 /******************************************************************************/ |
|
234 |
|
235 if (typeof reportCompare === "function") |
|
236 reportCompare(true, true); |
|
237 |
|
238 print("All tests passed!"); |