Bug 771742 - Reimplement the Date.prototype.set<unit of time> functions in terms of their spec steps, and remove the hard-to-understand date_makeTime. r=luke

--HG--
extra : rebase_source : cf070e258834853ebe24ec9cf0027de1d194a62c
This commit is contained in:
Jeff Walden 2012-07-06 13:53:10 -07:00
parent 49aaa718a1
commit d68f5c5e3e

View File

@ -1783,149 +1783,330 @@ date_setTime(JSContext *cx, unsigned argc, Value *vp)
return SetUTCTime(cx, thisObj, TimeClip(result), &args.rval());
}
static bool
GetMsecsOrDefault(JSContext *cx, const CallArgs &args, unsigned i, double t, double *millis)
{
if (args.length() <= i) {
*millis = msFromTime(t);
return true;
}
return ToNumber(cx, args[i], millis);
}
static bool
GetSecsOrDefault(JSContext *cx, const CallArgs &args, unsigned i, double t, double *sec)
{
if (args.length() <= i) {
*sec = SecFromTime(t);
return true;
}
return ToNumber(cx, args[i], sec);
}
static bool
GetMinsOrDefault(JSContext *cx, const CallArgs &args, unsigned i, double t, double *mins)
{
if (args.length() <= i) {
*mins = MinFromTime(t);
return true;
}
return ToNumber(cx, args[i], mins);
}
/* ES5 15.9.5.28. */
static JSBool
date_makeTime(JSContext *cx, Native native, unsigned maxargs, JSBool local, unsigned argc, Value *vp)
date_setMilliseconds(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject thisObj(cx);
if (!NonGenericMethodGuard(cx, args, native, &DateClass, thisObj.address()))
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setMilliseconds, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
double result = thisObj->getDateUTCTime().toNumber();
/* Step 1. */
double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
/*
* Satisfy the ECMA rule that if a function is called with
* fewer arguments than the specified formal arguments, the
* remaining arguments are set to undefined. Seems like all
* the Date.setWhatever functions in ECMA are only varargs
* beyond the first argument; this should be set to undefined
* if it's not given. This means that "d = new Date();
* d.setMilliseconds()" returns NaN. Blech.
*/
if (args.length() == 0) {
SetDateToNaN(cx, thisObj, &args.rval());
return true;
}
/* Step 2. */
double milli;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &milli))
return false;
double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
unsigned numNums = Min(args.length(), maxargs);
JS_ASSERT(numNums <= 4);
double nums[4];
bool argIsNotFinite = false;
for (unsigned i = 0; i < numNums; i++) {
if (!ToNumber(cx, args[i], &nums[i]))
return false;
if (!MOZ_DOUBLE_IS_FINITE(nums[i])) {
argIsNotFinite = true;
} else {
nums[i] = ToInteger(nums[i]);
}
}
/* Step 3. */
double u = TimeClip(UTC(MakeDate(Day(t), time), cx));
/*
* Return NaN if the date is already NaN, but don't short-circuit argument
* evaluation.
*/
if (!MOZ_DOUBLE_IS_FINITE(result)) {
args.rval().setNumber(result);
return true;
}
/* set Date to NaN, after argument evaluation. */
if (argIsNotFinite) {
SetDateToNaN(cx, thisObj, &args.rval());
return true;
}
double lorutime; /* Local or UTC version of *date */
if (local)
lorutime = LocalTime(result, cx);
else
lorutime = result;
double *argp = nums;
double *stop = argp + numNums;
double hour;
if (maxargs >= 4 && argp < stop)
hour = *argp++;
else
hour = HourFromTime(lorutime);
double min;
if (maxargs >= 3 && argp < stop)
min = *argp++;
else
min = MinFromTime(lorutime);
double sec;
if (maxargs >= 2 && argp < stop)
sec = *argp++;
else
sec = SecFromTime(lorutime);
double msec;
if (maxargs >= 1 && argp < stop)
msec = *argp;
else
msec = msFromTime(lorutime);
double msec_time = MakeTime(hour, min, sec, msec);
result = MakeDate(Day(lorutime), msec_time);
if (local)
result = UTC(result, cx);
return SetUTCTime(cx, thisObj, TimeClip(result), &args.rval());
}
static JSBool
date_setMilliseconds(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setMilliseconds, 1, JS_TRUE, argc, vp);
/* Steps 4-5. */
return SetUTCTime(cx, thisObj, u, &args.rval());
}
/* ES5 15.9.5.29. */
static JSBool
date_setUTCMilliseconds(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setUTCMilliseconds, 1, JS_FALSE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setUTCMilliseconds, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = thisObj->getDateUTCTime().toNumber();
/* Step 2. */
double milli;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &milli))
return false;
double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli);
/* Step 3. */
double v = TimeClip(MakeDate(Day(t), time));
/* Steps 4-5. */
return SetUTCTime(cx, thisObj, v, &args.rval());
}
/* ES5 15.9.5.30. */
static JSBool
date_setSeconds(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setSeconds, 2, JS_TRUE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setSeconds, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
/* Step 2. */
double s;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &s))
return false;
/* Step 3. */
double milli;
if (!GetMsecsOrDefault(cx, args, 1, t, &milli))
return false;
/* Step 4. */
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
/* Step 5. */
double u = TimeClip(UTC(date, cx));
/* Steps 6-7. */
return SetUTCTime(cx, thisObj, u, &args.rval());
}
/* ES5 15.9.5.31. */
static JSBool
date_setUTCSeconds(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setUTCSeconds, 2, JS_FALSE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setUTCSeconds, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = thisObj->getDateUTCTime().toNumber();
/* Step 2. */
double s;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &s))
return false;
/* Step 3. */
double milli;
if (!GetMsecsOrDefault(cx, args, 1, t, &milli))
return false;
/* Step 4. */
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli));
/* Step 5. */
double v = TimeClip(date);
/* Steps 6-7. */
return SetUTCTime(cx, thisObj, v, &args.rval());
}
/* ES5 15.9.5.32. */
static JSBool
date_setMinutes(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setMinutes, 3, JS_TRUE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setMinutes, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
/* Step 2. */
double m;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &m))
return false;
/* Step 3. */
double s;
if (!GetSecsOrDefault(cx, args, 1, t, &s))
return false;
/* Step 4. */
double milli;
if (!GetMsecsOrDefault(cx, args, 2, t, &milli))
return false;
/* Step 5. */
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
/* Step 6. */
double u = TimeClip(UTC(date, cx));
/* Steps 7-8. */
return SetUTCTime(cx, thisObj, u, &args.rval());
}
/* ES5 15.9.5.33. */
static JSBool
date_setUTCMinutes(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setUTCMinutes, 3, JS_FALSE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setUTCMinutes, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = thisObj->getDateUTCTime().toNumber();
/* Step 2. */
double m;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &m))
return false;
/* Step 3. */
double s;
if (!GetSecsOrDefault(cx, args, 1, t, &s))
return false;
/* Step 4. */
double milli;
if (!GetMsecsOrDefault(cx, args, 2, t, &milli))
return false;
/* Step 5. */
double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli));
/* Step 6. */
double v = TimeClip(date);
/* Steps 7-8. */
return SetUTCTime(cx, thisObj, v, &args.rval());
}
/* ES5 15.9.5.34. */
static JSBool
date_setHours(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setHours, 4, JS_TRUE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setHours, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
/* Step 2. */
double h;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &h))
return false;
/* Step 3. */
double m;
if (!GetMinsOrDefault(cx, args, 1, t, &m))
return false;
/* Step 4. */
double s;
if (!GetSecsOrDefault(cx, args, 2, t, &s))
return false;
/* Step 5. */
double milli;
if (!GetMsecsOrDefault(cx, args, 3, t, &milli))
return false;
/* Step 6. */
double date = MakeDate(Day(t), MakeTime(h, m, s, milli));
/* Step 6. */
double u = TimeClip(UTC(date, cx));
/* Steps 7-8. */
return SetUTCTime(cx, thisObj, u, &args.rval());
}
/* ES5 15.9.5.35. */
static JSBool
date_setUTCHours(JSContext *cx, unsigned argc, Value *vp)
{
return date_makeTime(cx, date_setUTCHours, 4, JS_FALSE, argc, vp);
CallArgs args = CallArgsFromVp(argc, vp);
Rooted<JSObject*> thisObj(cx);
if (!NonGenericMethodGuard(cx, args, date_setUTCHours, &DateClass, thisObj.address()))
return false;
if (!thisObj)
return true;
/* Step 1. */
double t = thisObj->getDateUTCTime().toNumber();
/* Step 2. */
double h;
if (!ToNumber(cx, args.length() > 0 ? args[0] : UndefinedValue(), &h))
return false;
/* Step 3. */
double m;
if (!GetMinsOrDefault(cx, args, 1, t, &m))
return false;
/* Step 4. */
double s;
if (!GetSecsOrDefault(cx, args, 2, t, &s))
return false;
/* Step 5. */
double milli;
if (!GetMsecsOrDefault(cx, args, 3, t, &milli))
return false;
/* Step 6. */
double newDate = MakeDate(Day(t), MakeTime(h, m, s, milli));
/* Step 7. */
double v = TimeClip(newDate);
/* Steps 8-9. */
return SetUTCTime(cx, thisObj, v, &args.rval());
}
static JSBool