Source code

Revision control

Copy as Markdown

Other Tools

// Any copyright is dedicated to the Public Domain.
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!");