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