| // Any copyright is dedicated to the Public Domain. |
| // http://creativecommons.org/licenses/publicdomain/ |
| |
| var gTestfile = 'toJSON-01.js'; |
| //----------------------------------------------------------------------------- |
| var BUGNUMBER = 584811; |
| var summary = "Date.prototype.toJSON isn't to spec"; |
| |
| print(BUGNUMBER + ": " + summary); |
| |
| /************** |
| * BEGIN TEST * |
| **************/ |
| |
| var called; |
| |
| var dateToJSON = Date.prototype.toJSON; |
| assertEq(Date.prototype.hasOwnProperty("toJSON"), true); |
| assertEq(typeof dateToJSON, "function"); |
| |
| // brief test to exercise this outside of isolation, just for sanity |
| var invalidDate = new Date(); |
| invalidDate.setTime(NaN); |
| assertEq(JSON.stringify({ p: invalidDate }), '{"p":null}'); |
| |
| |
| /* 15.9.5.44 Date.prototype.toJSON ( key ) */ |
| assertEq(dateToJSON.length, 1); |
| |
| /* |
| * 1. Let O be the result of calling ToObject, giving it the this value as its |
| * argument. |
| */ |
| try |
| { |
| dateToJSON.call(null); |
| throw new Error("should have thrown a TypeError"); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, |
| "ToObject throws TypeError for null/undefined"); |
| } |
| |
| try |
| { |
| dateToJSON.call(undefined); |
| throw new Error("should have thrown a TypeError"); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, |
| "ToObject throws TypeError for null/undefined"); |
| } |
| |
| |
| /* |
| * 2. Let tv be ToPrimitive(O, hint Number). |
| * ...expands to: |
| * 1. Let valueOf be the result of calling the [[Get]] internal method of object O with argument "valueOf". |
| * 2. If IsCallable(valueOf) is true then, |
| * a. Let val be the result of calling the [[Call]] internal method of valueOf, with O as the this value and |
| * an empty argument list. |
| * b. If val is a primitive value, return val. |
| * 3. Let toString be the result of calling the [[Get]] internal method of object O with argument "toString". |
| * 4. If IsCallable(toString) is true then, |
| * a. Let str be the result of calling the [[Call]] internal method of toString, with O as the this value and |
| * an empty argument list. |
| * b. If str is a primitive value, return str. |
| * 5. Throw a TypeError exception. |
| */ |
| try |
| { |
| var r = dateToJSON.call({ get valueOf() { throw 17; } }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e, 17, "bad exception: " + e); |
| } |
| |
| called = false; |
| assertEq(dateToJSON.call({ valueOf: null, |
| toString: function() { called = true; return 12; }, |
| toISOString: function() { return "ohai"; } }), |
| "ohai"); |
| assertEq(called, true); |
| |
| called = false; |
| assertEq(dateToJSON.call({ valueOf: function() { called = true; return 42; }, |
| toISOString: function() { return null; } }), |
| null); |
| assertEq(called, true); |
| |
| try |
| { |
| called = false; |
| dateToJSON.call({ valueOf: function() { called = true; return {}; }, |
| get toString() { throw 42; } }); |
| } |
| catch (e) |
| { |
| assertEq(called, true); |
| assertEq(e, 42, "bad exception: " + e); |
| } |
| |
| called = false; |
| assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, |
| get toString() { return function() { return 8675309; }; }, |
| toISOString: function() { return true; } }), |
| true); |
| assertEq(called, true); |
| |
| var asserted = false; |
| called = false; |
| assertEq(dateToJSON.call({ valueOf: function() { called = true; return {}; }, |
| get toString() |
| { |
| assertEq(called, true); |
| asserted = true; |
| return function() { return 8675309; }; |
| }, |
| toISOString: function() { return NaN; } }), |
| NaN); |
| assertEq(asserted, true); |
| |
| try |
| { |
| var r = dateToJSON.call({ valueOf: null, toString: null, |
| get toISOString() |
| { |
| throw new Error("shouldn't have been gotten"); |
| } }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, "bad exception: " + e); |
| } |
| |
| |
| /* 3. If tv is a Number and is not finite, return null. */ |
| assertEq(dateToJSON.call({ valueOf: function() { return Infinity; } }), null); |
| assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; } }), null); |
| assertEq(dateToJSON.call({ valueOf: function() { return NaN; } }), null); |
| |
| assertEq(dateToJSON.call({ valueOf: function() { return Infinity; }, |
| toISOString: function() { return {}; } }), null); |
| assertEq(dateToJSON.call({ valueOf: function() { return -Infinity; }, |
| toISOString: function() { return []; } }), null); |
| assertEq(dateToJSON.call({ valueOf: function() { return NaN; }, |
| toISOString: function() { return undefined; } }), null); |
| |
| |
| /* |
| * 4. Let toISO be the result of calling the [[Get]] internal method of O with |
| * argument "toISOString". |
| */ |
| try |
| { |
| var r = dateToJSON.call({ get toISOString() { throw 42; } }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e, 42, "bad exception: " + e); |
| } |
| |
| |
| /* 5. If IsCallable(toISO) is false, throw a TypeError exception. */ |
| try |
| { |
| var r = dateToJSON.call({ toISOString: null }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, "bad exception: " + e); |
| } |
| |
| try |
| { |
| var r = dateToJSON.call({ toISOString: undefined }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, "bad exception: " + e); |
| } |
| |
| try |
| { |
| var r = dateToJSON.call({ toISOString: "oogabooga" }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, "bad exception: " + e); |
| } |
| |
| try |
| { |
| var r = dateToJSON.call({ toISOString: Math.PI }); |
| throw new Error("didn't throw, returned: " + r); |
| } |
| catch (e) |
| { |
| assertEq(e instanceof TypeError, true, "bad exception: " + e); |
| } |
| |
| |
| /* |
| * 6. Return the result of calling the [[Call]] internal method of toISO with O |
| * as the this value and an empty argument list. |
| */ |
| var o = |
| { |
| toISOString: function(a) |
| { |
| called = true; |
| assertEq(this, o); |
| assertEq(a, undefined); |
| assertEq(arguments.length, 0); |
| return obj; |
| } |
| }; |
| var obj = {}; |
| called = false; |
| assertEq(dateToJSON.call(o), obj, "should have gotten obj back"); |
| assertEq(called, true); |
| |
| |
| /******************************************************************************/ |
| |
| if (typeof reportCompare === "function") |
| reportCompare(true, true); |
| |
| print("All tests passed!"); |