/[jscoverage]/trunk/js/jsdate.cpp
ViewVC logotype

Diff of /trunk/js/jsdate.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 460 by siliconforks, Sat Sep 26 23:15:22 2009 UTC revision 507 by siliconforks, Sun Jan 10 07:23:34 2010 UTC
# Line 1  Line 1 
1  /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-  /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2   * vim: set ts=8 sw=4 et tw=78:   * vim: set ts=8 sw=4 et tw=78:
3   *   *
4   * ***** BEGIN LICENSE BLOCK *****   * ***** BEGIN LICENSE BLOCK *****
# Line 51  Line 51 
51   * Frederick Brooks, 'The Second-System Effect'.   * Frederick Brooks, 'The Second-System Effect'.
52   */   */
53    
 #include "jsstddef.h"  
54  #include <ctype.h>  #include <ctype.h>
55  #include <locale.h>  #include <locale.h>
56  #include <math.h>  #include <math.h>
57  #include <stdlib.h>  #include <stdlib.h>
58  #include <string.h>  #include <string.h>
59  #include "jstypes.h"  #include "jstypes.h"
60    #include "jsstdint.h"
61  #include "jsprf.h"  #include "jsprf.h"
62  #include "prmjtime.h"  #include "prmjtime.h"
63  #include "jsutil.h" /* Added by JSIFY */  #include "jsutil.h" /* Added by JSIFY */
# Line 218  Line 218 
218   * The following array contains the day of year for the first day of   * The following array contains the day of year for the first day of
219   * each month, where index 0 is January, and day 0 is January 1.   * each month, where index 0 is January, and day 0 is January 1.
220   */   */
221  static jsdouble firstDayOfMonth[2][12] = {  static jsdouble firstDayOfMonth[2][13] = {
222      {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0},      {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0, 365.0},
223      {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0}      {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0, 366.0}
224  };  };
225    
226  #define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m];  #define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m]
227    
228    static intN
229    DaysInMonth(jsint year, jsint month)
230    {
231        JSBool leap = (DaysInYear(year) == 366);
232        intN result = DayFromMonth(month, leap) - DayFromMonth(month-1, leap);
233        return result;
234    }
235    
236  static intN  static intN
237  MonthFromTime(jsdouble t)  MonthFromTime(jsdouble t)
# Line 494  Line 502 
502      JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |      JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
503      JSCLASS_HAS_CACHED_PROTO(JSProto_Date),      JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
504      JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,      JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
505      JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,      JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   NULL,
506      JSCLASS_NO_OPTIONAL_MEMBERS      JSCLASS_NO_OPTIONAL_MEMBERS
507  };  };
508    
# Line 626  Line 634 
634      return js_NewNumberInRootedValue(cx, msec_time, vp);      return js_NewNumberInRootedValue(cx, msec_time, vp);
635  }  }
636    
637    /*
638     * Read and convert decimal digits from s[*i] into *result
639     * while *i < limit.
640     *
641     * Succeed if any digits are converted. Advance *i only
642     * as digits are consumed.
643     */
644    static JSBool
645    digits(size_t *result, const jschar *s, size_t *i, size_t limit)
646    {
647        size_t init = *i;
648        *result = 0;
649        while (*i < limit &&
650               ('0' <= s[*i] && s[*i] <= '9')) {
651            *result *= 10;
652            *result += (s[*i] - '0');
653            ++(*i);
654        }
655        return (*i != init);
656    }
657    
658    /*
659     * Read and convert decimal digits to the right of a decimal point,
660     * representing a fractional integer, from s[*i] into *result
661     * while *i < limit.
662     *
663     * Succeed if any digits are converted. Advance *i only
664     * as digits are consumed.
665     */
666    static JSBool
667    fractional(jsdouble *result, const jschar *s, size_t *i, size_t limit)
668    {
669        jsdouble factor = 0.1;
670        size_t init = *i;
671        *result = 0.0;
672        while (*i < limit &&
673               ('0' <= s[*i] && s[*i] <= '9')) {
674            *result += (s[*i] - '0') * factor;
675            factor *= 0.1;
676            ++(*i);
677        }
678        return (*i != init);
679    }
680    
681    /*
682     * Read and convert exactly n decimal digits from s[*i]
683     * to s[min(*i+n,limit)] into *result.
684     *
685     * Succeed if exactly n digits are converted. Advance *i only
686     * on success.
687     */
688    static JSBool
689    ndigits(size_t n, size_t *result, const jschar *s, size_t* i, size_t limit)
690    {
691        size_t init = *i;
692    
693        if (digits(result, s, i, JS_MIN(limit, init+n)))
694            return ((*i - init) == n);
695        
696        *i = init;
697        return JS_FALSE;
698    }
699    
700    /*
701     * Parse a string in one of the date-time formats given by the W3C
702     * "NOTE-datetime" specification. These formats make up a restricted
703     * profile of the ISO 8601 format. Quoted here:
704     *
705     *   The formats are as follows. Exactly the components shown here
706     *   must be present, with exactly this punctuation. Note that the "T"
707     *   appears literally in the string, to indicate the beginning of the
708     *   time element, as specified in ISO 8601.
709     *
710     *   Any combination of the date formats with the time formats is
711     *   allowed, and also either the date or the time can be missing.
712     *
713     *   The specification is silent on the meaning when fields are
714     *   ommitted so the interpretations are a guess, but hopefully a
715     *   reasonable one. We default the month to January, the day to the
716     *   1st, and hours minutes and seconds all to 0. If the date is
717     *   missing entirely then we assume 1970-01-01 so that the time can
718     *   be aded to a date later. If the time is missing then we assume
719     *   00:00 UTC.  If the time is present but the time zone field is
720     *   missing then we use local time.
721     *
722     * Date part:
723     *
724     *  Year:
725     *     YYYY (eg 1997)
726     *
727     *  Year and month:
728     *     YYYY-MM (eg 1997-07)
729     *
730     *  Complete date:
731     *     YYYY-MM-DD (eg 1997-07-16)
732     *
733     * Time part:
734     *
735     *  Hours and minutes:
736     *     Thh:mmTZD (eg T19:20+01:00)
737     *
738     *  Hours, minutes and seconds:
739     *     Thh:mm:ssTZD (eg T19:20:30+01:00)
740     *
741     *  Hours, minutes, seconds and a decimal fraction of a second:
742     *     Thh:mm:ss.sTZD (eg T19:20:30.45+01:00)
743     *
744     * where:
745     *
746     *   YYYY = four-digit year or six digit year as +YYYYYY or -YYYYYY
747     *   MM   = two-digit month (01=January, etc.)
748     *   DD   = two-digit day of month (01 through 31)
749     *   hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
750     *   mm   = two digits of minute (00 through 59)
751     *   ss   = two digits of second (00 through 59)
752     *   s    = one or more digits representing a decimal fraction of a second
753     *   TZD  = time zone designator (Z or +hh:mm or -hh:mm or missing for local)
754     */
755    
756    static JSBool
757    date_parseISOString(JSString *str, jsdouble *result)
758    {
759        jsdouble msec;
760    
761        const jschar *s;
762        size_t limit;
763        size_t i = 0;
764        int tzMul = 1;
765        int dateMul = 1;
766        size_t year = 1970;
767        size_t month = 1;
768        size_t day = 1;
769        size_t hour = 0;
770        size_t min = 0;
771        size_t sec = 0;
772        jsdouble frac = 0;
773        bool isLocalTime = JS_FALSE;
774        size_t tzHour = 0;
775        size_t tzMin = 0;
776    
777    #define PEEK(ch) (i < limit && s[i] == ch)
778    
779    #define NEED(ch)                                                     \
780        JS_BEGIN_MACRO                                                   \
781            if (i >= limit || s[i] != ch) { goto syntax; } else { ++i; } \
782        JS_END_MACRO
783    
784    #define DONE_DATE_UNLESS(ch)                                            \
785        JS_BEGIN_MACRO                                                      \
786            if (i >= limit || s[i] != ch) { goto done_date; } else { ++i; } \
787        JS_END_MACRO
788    
789    #define DONE_UNLESS(ch)                                            \
790        JS_BEGIN_MACRO                                                 \
791            if (i >= limit || s[i] != ch) { goto done; } else { ++i; } \
792        JS_END_MACRO
793    
794    #define NEED_NDIGITS(n, field)                                      \
795        JS_BEGIN_MACRO                                                  \
796            if (!ndigits(n, &field, s, &i, limit)) { goto syntax; }     \
797        JS_END_MACRO
798    
799        str->getCharsAndLength(s, limit);
800    
801        if (PEEK('+') || PEEK('-')) {
802            if (PEEK('-'))
803                dateMul = -1;
804            ++i;
805            NEED_NDIGITS(6, year);
806        } else if (!PEEK('T')) {
807            NEED_NDIGITS(4, year);
808        }
809        DONE_DATE_UNLESS('-');
810        NEED_NDIGITS(2, month);
811        DONE_DATE_UNLESS('-');
812        NEED_NDIGITS(2, day);
813    
814     done_date:
815        DONE_UNLESS('T');
816        NEED_NDIGITS(2, hour);
817        NEED(':');
818        NEED_NDIGITS(2, min);
819    
820        if (PEEK(':')) {
821            ++i;
822            NEED_NDIGITS(2, sec);
823            if (PEEK('.')) {
824                ++i;
825                if (!fractional(&frac, s, &i, limit))
826                    goto syntax;
827            }
828        }
829    
830        if (PEEK('Z')) {
831            ++i;
832        } else if (PEEK('+') || PEEK('-')) {
833            if (PEEK('-'))
834                tzMul = -1;
835            ++i;
836            NEED_NDIGITS(2, tzHour);
837            NEED(':');
838            NEED_NDIGITS(2, tzMin);
839        } else {
840            isLocalTime = JS_TRUE;
841        }
842    
843     done:
844        if (year > 275943 // ceil(1e8/365) + 1970
845            || (month == 0 || month > 12)
846            || (day == 0 || day > size_t(DaysInMonth(year,month)))
847            || hour > 24
848            || ((hour == 24) && (min > 0 || sec > 0))
849            || min > 59
850            || sec > 59
851            || tzHour > 23
852            || tzMin > 59)
853            goto syntax;
854    
855        if (i != limit)
856            goto syntax;
857    
858        month -= 1; /* convert month to 0-based */
859    
860        msec = date_msecFromDate(dateMul * (jsdouble)year, month, day,
861                                 hour, min, sec,
862                                 frac * 1000.0);;
863    
864        if (isLocalTime) {
865            msec = UTC(msec);
866        } else {
867            msec -= ((tzMul) * ((tzHour * msPerHour)
868                                + (tzMin * msPerMinute)));
869        }
870    
871        if (msec < -8.64e15 || msec > 8.64e15)
872            goto syntax;
873    
874        *result = msec;
875    
876        return JS_TRUE;
877    
878     syntax:
879        /* syntax error */
880        *result = 0;
881        return JS_FALSE;
882    
883    #undef PEEK
884    #undef NEED
885    #undef DONE_UNLESS
886    #undef NEED_NDIGITS
887    }
888    
889  static JSBool  static JSBool
890  date_parseString(JSString *str, jsdouble *result)  date_parseString(JSString *str, jsdouble *result)
891  {  {
# Line 648  Line 908 
908      int temp;      int temp;
909      JSBool seenmonthname = JS_FALSE;      JSBool seenmonthname = JS_FALSE;
910    
911      JSSTRING_CHARS_AND_LENGTH(str, s, limit);      if (date_parseISOString(str, result))
912            return JS_TRUE;
913    
914        str->getCharsAndLength(s, limit);
915      if (limit == 0)      if (limit == 0)
916          goto syntax;          goto syntax;
917      while (i < limit) {      while (i < limit) {
# Line 876  Line 1139 
1139          min = 0;          min = 0;
1140      if (hour < 0)      if (hour < 0)
1141          hour = 0;          hour = 0;
     if (tzoffset == -1) { /* no time zone specified, have to use local */  
         jsdouble msec_time;  
         msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);  
1142    
1143          *result = UTC(msec_time);      msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
1144          return JS_TRUE;  
1145        if (tzoffset == -1) { /* no time zone specified, have to use local */
1146            msec = UTC(msec);
1147        } else {
1148            msec += tzoffset * msPerMinute;
1149      }      }
1150    
     msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);  
     msec += tzoffset * msPerMinute;  
1151      *result = msec;      *result = msec;
1152      return JS_TRUE;      return JS_TRUE;
1153    
# Line 951  Line 1213 
1213      return JS_TRUE;      return JS_TRUE;
1214  }  }
1215    
1216  /*  static void
1217   * Set UTC time slot with a pointer pointing to a jsdouble. This function is  SetDateToNaN(JSContext *cx, JSObject *obj, jsval *vp = NULL)
  * used only for setting UTC time to some predefined values, such as NaN.  
  *  
  * It also invalidates cached local time.  
  */  
 static JSBool  
 SetUTCTimePtr(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)  
1218  {  {
1219      if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))      JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_DateClass);
         return JS_FALSE;  
     JS_ASSERT_IF(!vp, STOBJ_GET_CLASS(obj) == &js_DateClass);  
1220    
1221      /* Invalidate local time cache. */      jsval nan = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
1222      obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);      obj->fslots[JSSLOT_LOCAL_TIME] = nan;
1223      obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(dp);      obj->fslots[JSSLOT_UTC_TIME] = nan;
1224      return JS_TRUE;      if (vp)
1225            *vp = nan;
1226  }  }
1227    
1228  /*  /*
1229   * Set UTC time to a given time.   * Set UTC time to a given time and invalidate cached local time.
1230   */   */
1231  static JSBool  static JSBool
1232  SetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble t)  SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, jsval *vp = NULL)
1233  {  {
1234      jsdouble *dp = js_NewWeaklyRootedDouble(cx, t);      JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_DateClass);
1235      if (!dp)  
1236          return JS_FALSE;      obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
1237      return SetUTCTimePtr(cx, obj, vp, dp);      if (!js_NewDoubleInRootedValue(cx, t, &obj->fslots[JSSLOT_UTC_TIME]))
1238            return false;
1239        if (vp)
1240            *vp = obj->fslots[JSSLOT_UTC_TIME];
1241        return true;
1242  }  }
1243    
1244  /*  /*
# Line 1269  Line 1528 
1528  }  }
1529    
1530  static JSBool  static JSBool
 SetDateToNaN(JSContext *cx, jsval *vp)  
 {  
     JSObject *obj;  
   
     obj = JS_THIS_OBJECT(cx, vp);  
     if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))  
         return JS_FALSE;  
     *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);  
     return JS_TRUE;  
 }  
   
 static JSBool  
1531  date_setTime(JSContext *cx, uintN argc, jsval *vp)  date_setTime(JSContext *cx, uintN argc, jsval *vp)
1532  {  {
1533      jsdouble result;      JSObject *obj = JS_THIS_OBJECT(cx, vp);
1534        if (!JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
1535            return false;
1536    
1537      if (argc == 0)      if (argc == 0) {
1538          return SetDateToNaN(cx, vp);          SetDateToNaN(cx, obj, vp);
1539      result = js_ValueToNumber(cx, &vp[2]);          return true;
1540      if (JSVAL_IS_NULL(vp[2]))      }
         return JS_FALSE;  
   
     result = TIMECLIP(result);  
1541    
1542      if (!SetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, result))      jsdouble result = js_ValueToNumber(cx, &vp[2]);
1543          return JS_FALSE;      if (JSVAL_IS_NULL(vp[2]))
1544            return false;
1545    
1546      return js_NewNumberInRootedValue(cx, result, vp);      return SetUTCTime(cx, obj, TIMECLIP(result), vp);
1547  }  }
1548    
1549  static JSBool  static JSBool
# Line 1314  Line 1561 
1561    
1562      obj = JS_THIS_OBJECT(cx, vp);      obj = JS_THIS_OBJECT(cx, vp);
1563      if (!GetUTCTime(cx, obj, vp, &result))      if (!GetUTCTime(cx, obj, vp, &result))
1564          return JS_FALSE;          return false;
1565    
1566      /* just return NaN if the date is already NaN */      /* just return NaN if the date is already NaN */
1567      if (!JSDOUBLE_IS_FINITE(result))      if (!JSDOUBLE_IS_FINITE(result))
# Line 1329  Line 1576 
1576       * if it's not given.  This means that "d = new Date();       * if it's not given.  This means that "d = new Date();
1577       * d.setMilliseconds()" returns NaN.  Blech.       * d.setMilliseconds()" returns NaN.  Blech.
1578       */       */
1579      if (argc == 0)      if (argc == 0) {
1580          return SetDateToNaN(cx, vp);          SetDateToNaN(cx, obj, vp);
1581            return true;
1582        }
1583      if (argc > maxargs)      if (argc > maxargs)
1584          argc = maxargs;  /* clamp argc */          argc = maxargs;  /* clamp argc */
1585      JS_ASSERT(argc <= 4);      JS_ASSERT(argc <= 4);
# Line 1339  Line 1588 
1588      for (i = 0; i < argc; i++) {      for (i = 0; i < argc; i++) {
1589          args[i] = js_ValueToNumber(cx, &argv[i]);          args[i] = js_ValueToNumber(cx, &argv[i]);
1590          if (JSVAL_IS_NULL(argv[i]))          if (JSVAL_IS_NULL(argv[i]))
1591              return JS_FALSE;              return false;
1592          if (!JSDOUBLE_IS_FINITE(args[i]))          if (!JSDOUBLE_IS_FINITE(args[i])) {
1593              return SetDateToNaN(cx, vp);              SetDateToNaN(cx, obj, vp);
1594                return true;
1595            }
1596          args[i] = js_DoubleToInteger(args[i]);          args[i] = js_DoubleToInteger(args[i]);
1597      }      }
1598    
# Line 1382  Line 1633 
1633    
1634  /*     fprintf(stderr, "%f\n", result); */  /*     fprintf(stderr, "%f\n", result); */
1635    
1636      result = TIMECLIP(result);      return SetUTCTime(cx, obj, TIMECLIP(result), vp);
     if (!SetUTCTime(cx, obj, NULL, result))  
         return JS_FALSE;  
   
     return js_NewNumberInRootedValue(cx, result, vp);  
1637  }  }
1638    
1639  static JSBool  static JSBool
# Line 1450  Line 1697 
1697    
1698      obj = JS_THIS_OBJECT(cx, vp);      obj = JS_THIS_OBJECT(cx, vp);
1699      if (!GetUTCTime(cx, obj, vp, &result))      if (!GetUTCTime(cx, obj, vp, &result))
1700          return JS_FALSE;          return false;
1701    
1702      /* see complaint about ECMA in date_MakeTime */      /* see complaint about ECMA in date_MakeTime */
1703      if (argc == 0)      if (argc == 0) {
1704          return SetDateToNaN(cx, vp);          SetDateToNaN(cx, obj, vp);
1705            return true;
1706        }
1707      if (argc > maxargs)      if (argc > maxargs)
1708          argc = maxargs;   /* clamp argc */          argc = maxargs;   /* clamp argc */
1709      JS_ASSERT(1 <= argc && argc <= 3);      JS_ASSERT(1 <= argc && argc <= 3);
# Line 1464  Line 1713 
1713          args[i] = js_ValueToNumber(cx, &argv[i]);          args[i] = js_ValueToNumber(cx, &argv[i]);
1714          if (JSVAL_IS_NULL(argv[i]))          if (JSVAL_IS_NULL(argv[i]))
1715              return JS_FALSE;              return JS_FALSE;
1716          if (!JSDOUBLE_IS_FINITE(args[i]))          if (!JSDOUBLE_IS_FINITE(args[i])) {
1717              return SetDateToNaN(cx, vp);              SetDateToNaN(cx, obj, vp);
1718                return true;
1719            }
1720          args[i] = js_DoubleToInteger(args[i]);          args[i] = js_DoubleToInteger(args[i]);
1721      }      }
1722    
# Line 1502  Line 1753 
1753      if (local)      if (local)
1754          result = UTC(result);          result = UTC(result);
1755    
1756      result = TIMECLIP(result);      return SetUTCTime(cx, obj, TIMECLIP(result), vp);
     if (!SetUTCTime(cx, obj, NULL, result))  
         return JS_FALSE;  
   
     return js_NewNumberInRootedValue(cx, result, vp);  
1757  }  }
1758    
1759  static JSBool  static JSBool
# Line 1548  Line 1795 
1795  static JSBool  static JSBool
1796  date_setYear(JSContext *cx, uintN argc, jsval *vp)  date_setYear(JSContext *cx, uintN argc, jsval *vp)
1797  {  {
1798      JSObject *obj;      JSObject *obj = JS_THIS_OBJECT(cx, vp);
     jsdouble t;  
     jsdouble year;  
     jsdouble day;  
     jsdouble result;  
1799    
1800      obj = JS_THIS_OBJECT(cx, vp);      jsdouble result;
1801      if (!GetUTCTime(cx, obj, vp, &result))      if (!GetUTCTime(cx, obj, vp, &result))
1802          return JS_FALSE;          return false;
1803    
1804      if (argc == 0)      if (argc == 0) {
1805          return SetDateToNaN(cx, vp);          /* Call this only after GetUTCTime has verified that obj is Date. */
1806      year = js_ValueToNumber(cx, &vp[2]);          SetDateToNaN(cx, obj, vp);
1807      if (JSVAL_IS_NULL(vp[2]))          return true;
         return JS_FALSE;  
     if (!JSDOUBLE_IS_FINITE(year))  
         return SetDateToNaN(cx, vp);  
   
     year = js_DoubleToInteger(year);  
   
     if (!JSDOUBLE_IS_FINITE(result)) {  
         t = +0.0;  
     } else {  
         t = LocalTime(result);  
1808      }      }
1809    
1810        jsdouble year = js_ValueToNumber(cx, &vp[2]);
1811        if (JSVAL_IS_NULL(vp[2]))
1812            return false;
1813        if (!JSDOUBLE_IS_FINITE(year)) {
1814            SetDateToNaN(cx, obj, vp);
1815            return true;
1816        }
1817        year = js_DoubleToInteger(year);
1818      if (year >= 0 && year <= 99)      if (year >= 0 && year <= 99)
1819          year += 1900;          year += 1900;
1820    
1821      day = MakeDay(year, MonthFromTime(t), DateFromTime(t));      jsdouble t = JSDOUBLE_IS_FINITE(result) ? LocalTime(result) : +0.0;
1822        jsdouble day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
1823      result = MakeDate(day, TimeWithinDay(t));      result = MakeDate(day, TimeWithinDay(t));
1824      result = UTC(result);      result = UTC(result);
1825    
1826      result = TIMECLIP(result);      return SetUTCTime(cx, obj, TIMECLIP(result), vp);
     if (!SetUTCTime(cx, obj, NULL, result))  
         return JS_FALSE;  
   
     return js_NewNumberInRootedValue(cx, result, vp);  
1827  }  }
1828    
1829  /* constants for toString, toUTCString */  /* constants for toString, toUTCString */
# Line 1961  Line 2199 
2199    
2200      str = JS_NewString(cx, bytes, strlen(bytes));      str = JS_NewString(cx, bytes, strlen(bytes));
2201      if (!str) {      if (!str) {
2202          free(bytes);          js_free(bytes);
2203          return JS_FALSE;          return JS_FALSE;
2204      }      }
2205      *vp = STRING_TO_JSVAL(str);      *vp = STRING_TO_JSVAL(str);
# Line 2030  Line 2268 
2268  static JSFunctionSpec date_static_methods[] = {  static JSFunctionSpec date_static_methods[] = {
2269      JS_FN("UTC",                 date_UTC,                MAXARGS,0),      JS_FN("UTC",                 date_UTC,                MAXARGS,0),
2270      JS_FN("parse",               date_parse,              1,0),      JS_FN("parse",               date_parse,              1,0),
2271      JS_TN("now",                 date_now,                0,0, date_now_trcinfo),      JS_TN("now",                 date_now,                0,0, &date_now_trcinfo),
2272      JS_FS_END      JS_FS_END
2273  };  };
2274    
# Line 2087  Line 2325 
2325      JS_FN(js_toSource_str,       date_toSource,           0,0),      JS_FN(js_toSource_str,       date_toSource,           0,0),
2326  #endif  #endif
2327      JS_FN(js_toString_str,       date_toString,           0,0),      JS_FN(js_toString_str,       date_toString,           0,0),
2328      JS_TN(js_valueOf_str,        date_valueOf,            0,0, date_valueOf_trcinfo),      JS_TN(js_valueOf_str,        date_valueOf,            0,0, &date_valueOf_trcinfo),
2329      JS_FS_END      JS_FS_END
2330  };  };
2331    
 static jsdouble *  
 date_constructor(JSContext *cx, JSObject* obj)  
 {  
     jsdouble *date;  
   
     date = js_NewWeaklyRootedDouble(cx, 0.0);  
     if (!date)  
         return NULL;  
   
     obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);  
     obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);  
     return date;  
 }  
   
2332  JSBool  JSBool
2333  js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)  js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
2334  {  {
     jsdouble *date;  
     JSString *str;  
     jsdouble d;  
   
2335      /* Date called as function. */      /* Date called as function. */
2336      if (!JS_IsConstructing(cx))      if (!JS_IsConstructing(cx))
2337          return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, rval);          return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, rval);
2338    
2339      /* Date called as constructor. */      /* Date called as constructor. */
2340        jsdouble d;
2341      if (argc == 0) {      if (argc == 0) {
2342          date = date_constructor(cx, obj);          d = NowAsMillis();
         if (!date)  
             return JS_FALSE;  
         *date = NowAsMillis();  
2343      } else if (argc == 1) {      } else if (argc == 1) {
2344          if (!JSVAL_IS_STRING(argv[0])) {          if (!JSVAL_IS_STRING(argv[0])) {
2345              /* the argument is a millisecond number */              /* the argument is a millisecond number */
2346              d = js_ValueToNumber(cx, &argv[0]);              d = js_ValueToNumber(cx, &argv[0]);
2347              if (JSVAL_IS_NULL(argv[0]))              if (JSVAL_IS_NULL(argv[0]))
2348                  return JS_FALSE;                  return JS_FALSE;
2349              date = date_constructor(cx, obj);              d = TIMECLIP(d);
             if (!date)  
                 return JS_FALSE;  
             *date = TIMECLIP(d);  
2350          } else {          } else {
2351              /* the argument is a string; parse it. */              /* the argument is a string; parse it. */
2352              date = date_constructor(cx, obj);              JSString *str = js_ValueToString(cx, argv[0]);
             if (!date)  
                 return JS_FALSE;  
   
             str = js_ValueToString(cx, argv[0]);  
2353              if (!str)              if (!str)
2354                  return JS_FALSE;                  return JS_FALSE;
2355                argv[0] = STRING_TO_JSVAL(str);
2356    
2357              if (!date_parseString(str, date))              if (!date_parseString(str, &d))
2358                  *date = *cx->runtime->jsNaN;                  d = js_NaN;
2359              *date = TIMECLIP(*date);              else
2360                    d = TIMECLIP(d);
2361          }          }
2362      } else {      } else {
         jsdouble *date;  
2363          jsdouble msec_time;          jsdouble msec_time;
   
2364          if (!date_msecFromArgs(cx, argc, argv, &msec_time))          if (!date_msecFromArgs(cx, argc, argv, &msec_time))
2365              return JS_FALSE;              return JS_FALSE;
2366    
         date = date_constructor(cx, obj);  
         if (!date)  
             return JS_FALSE;  
   
2367          if (JSDOUBLE_IS_FINITE(msec_time)) {          if (JSDOUBLE_IS_FINITE(msec_time)) {
2368              msec_time = UTC(msec_time);              msec_time = UTC(msec_time);
2369              msec_time = TIMECLIP(msec_time);              msec_time = TIMECLIP(msec_time);
2370          }          }
2371            d = msec_time;
         *date = msec_time;  
2372      }      }
2373      return JS_TRUE;      return SetUTCTime(cx, obj, d);
2374  }  }
2375    
2376  JSObject *  JSObject *
2377  js_InitDateClass(JSContext *cx, JSObject *obj)  js_InitDateClass(JSContext *cx, JSObject *obj)
2378  {  {
2379      JSObject *proto;      JSObject *proto;
     jsdouble *proto_date;  
2380    
2381      /* set static LocalTZA */      /* set static LocalTZA */
2382      LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);      LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
# Line 2180  Line 2385 
2385      if (!proto)      if (!proto)
2386          return NULL;          return NULL;
2387    
2388        SetDateToNaN(cx, proto);
2389    
2390      /* Alias toUTCString with toGMTString.  (ECMA B.2.6) */      /* Alias toUTCString with toGMTString.  (ECMA B.2.6) */
2391      if (!JS_AliasProperty(cx, proto, "toUTCString", "toGMTString"))      if (!JS_AliasProperty(cx, proto, "toUTCString", "toGMTString"))
2392          return NULL;          return NULL;
2393    
     /* Set the value of the Date.prototype date to NaN */  
     proto_date = date_constructor(cx, proto);  
     if (!proto_date)  
         return NULL;  
     *proto_date = *cx->runtime->jsNaN;  
   
2394      return proto;      return proto;
2395  }  }
2396    
2397  JS_FRIEND_API(JSObject *)  JS_FRIEND_API(JSObject *)
2398  js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)  js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
2399  {  {
2400      JSObject *obj;      JSObject *obj = js_NewObject(cx, &js_DateClass, NULL, NULL);
2401      jsdouble *date;      if (!obj || !SetUTCTime(cx, obj, msec_time))
   
     obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);  
     if (!obj)  
2402          return NULL;          return NULL;
   
     date = date_constructor(cx, obj);  
     if (!date)  
         return NULL;  
   
     *date = msec_time;  
2403      return obj;      return obj;
2404  }  }
2405    
# Line 2329  Line 2521 
2521                                msFromTime(local));                                msFromTime(local));
2522    
2523      /* SetUTCTime also invalidates local time cache. */      /* SetUTCTime also invalidates local time cache. */
2524      SetUTCTime(cx, obj, NULL, UTC(local));      SetUTCTime(cx, obj, UTC(local));
2525  }  }
2526    
2527  JS_FRIEND_API(void)  JS_FRIEND_API(void)
# Line 2353  Line 2545 
2545                                MinFromTime(local),                                MinFromTime(local),
2546                                SecFromTime(local),                                SecFromTime(local),
2547                                msFromTime(local));                                msFromTime(local));
2548      SetUTCTime(cx, obj, NULL, UTC(local));      SetUTCTime(cx, obj, UTC(local));
2549  }  }
2550    
2551  JS_FRIEND_API(void)  JS_FRIEND_API(void)
# Line 2374  Line 2566 
2566                                MinFromTime(local),                                MinFromTime(local),
2567                                SecFromTime(local),                                SecFromTime(local),
2568                                msFromTime(local));                                msFromTime(local));
2569      SetUTCTime(cx, obj, NULL, UTC(local));      SetUTCTime(cx, obj, UTC(local));
2570  }  }
2571    
2572  JS_FRIEND_API(void)  JS_FRIEND_API(void)
# Line 2394  Line 2586 
2586                                MinFromTime(local),                                MinFromTime(local),
2587                                SecFromTime(local),                                SecFromTime(local),
2588                                msFromTime(local));                                msFromTime(local));
2589      SetUTCTime(cx, obj, NULL, UTC(local));      SetUTCTime(cx, obj, UTC(local));
2590  }  }
2591    
2592  JS_FRIEND_API(void)  JS_FRIEND_API(void)
# Line 2414  Line 2606 
2606                                minutes,                                minutes,
2607                                SecFromTime(local),                                SecFromTime(local),
2608                                msFromTime(local));                                msFromTime(local));
2609      SetUTCTime(cx, obj, NULL, UTC(local));      SetUTCTime(cx, obj, UTC(local));
2610  }  }
2611    
2612  JS_FRIEND_API(void)  JS_FRIEND_API(void)
# Line 2434  Line 2626 
2626                                MinFromTime(local),                                MinFromTime(local),
2627                                seconds,                                seconds,
2628                                msFromTime(local));                                msFromTime(local));
2629      SetUTCTime(cx, obj, NULL, UTC(local));      SetUTCTime(cx, obj, UTC(local));
2630  }  }
2631    
2632  JS_FRIEND_API(jsdouble)  JS_FRIEND_API(jsdouble)
# Line 2449  Line 2641 
2641  #ifdef JS_THREADSAFE  #ifdef JS_THREADSAFE
2642  #include "prinrval.h"  #include "prinrval.h"
2643    
2644  uint32  JS_FRIEND_API(uint32)
2645  js_IntervalNow()  js_IntervalNow()
2646  {  {
2647      return uint32(PR_IntervalToMilliseconds(PR_IntervalNow()));      return uint32(PR_IntervalToMilliseconds(PR_IntervalNow()));
2648  }  }
2649    
2650  #else /* !JS_THREADSAFE */  #else /* !JS_THREADSAFE */
2651    
2652  uint32  JS_FRIEND_API(uint32)
2653  js_IntervalNow()  js_IntervalNow()
2654  {  {
2655      return uint32(PRMJ_Now() / PRMJ_USEC_PER_MSEC);      return uint32(PRMJ_Now() / PRMJ_USEC_PER_MSEC);
2656  }  }

Legend:
Removed from v.460  
changed lines
  Added in v.507

  ViewVC Help
Powered by ViewVC 1.1.24