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