Changeset 16780 in webkit


Ignore:
Timestamp:
Oct 4, 2006 11:36:29 AM (17 years ago)
Author:
kmccullo
Message:

Reviewed by GGaren

  • This is a big makeover for our Date implemenetation. This solves many platform specific issues, specifically dates before 1970, and simplifies some ugly code. The purpose of this was to get us to pass many of the JavaScriptCore tests on windows.
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • kjs/DateMath.cpp: Added. (KJS::): (KJS::daysInYear): (KJS::daysFrom1970ToYear): (KJS::msFrom1970ToYear): (KJS::msToDays): (KJS::msToYear): (KJS::isLeapYear): (KJS::isInLeapYear): (KJS::dayInYear): (KJS::msToMilliseconds): (KJS::msToWeekDay): (KJS::msToSeconds): (KJS::msToMinutes): (KJS::msToHours): (KJS::msToMonth): (KJS::msToDayInMonth): (KJS::monthToDayInYear): (KJS::timeToMseconds): (KJS::dateToDayInYear): (KJS::equivalentYearForDST): (KJS::getUTCOffset): (KJS::getDSTOffsetSimple): (KJS::getDSTOffset): (KJS::localTimeToUTC): (KJS::UTCToLocalTime): (KJS::dateToMseconds): (KJS::msToTM): (KJS::isDST):
  • kjs/DateMath.h: Added. (KJS::):
  • kjs/date_object.cpp: (KJS::gmtoffset): (KJS::formatTime): (KJS::DateInstance::getTime): (KJS::DateInstance::getUTCTime): (KJS::DateProtoFunc::callAsFunction): (KJS::DateObjectImp::construct): (KJS::DateObjectFuncImp::callAsFunction): (KJS::parseDate):
  • kjs/testkjs.cpp:
  • os-win32/stdint.h:
Location:
trunk/JavaScriptCore
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r16716 r16780  
     12006-10-04  Kevin McCullough  <KMcCullough@apple.com>
     2
     3        Reviewed by GGaren
     4
     5        - This is a big makeover for our Date implemenetation.  This solves many platform specific issues, specifically dates before 1970, and simplifies some ugly code.  The purpose of this was to get us to pass many of the JavaScriptCore tests on windows.
     6
     7        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     8        * JavaScriptCore.xcodeproj/project.pbxproj:
     9        * kjs/DateMath.cpp: Added.
     10        (KJS::):
     11        (KJS::daysInYear):
     12        (KJS::daysFrom1970ToYear):
     13        (KJS::msFrom1970ToYear):
     14        (KJS::msToDays):
     15        (KJS::msToYear):
     16        (KJS::isLeapYear):
     17        (KJS::isInLeapYear):
     18        (KJS::dayInYear):
     19        (KJS::msToMilliseconds):
     20        (KJS::msToWeekDay):
     21        (KJS::msToSeconds):
     22        (KJS::msToMinutes):
     23        (KJS::msToHours):
     24        (KJS::msToMonth):
     25        (KJS::msToDayInMonth):
     26        (KJS::monthToDayInYear):
     27        (KJS::timeToMseconds):
     28        (KJS::dateToDayInYear):
     29        (KJS::equivalentYearForDST):
     30        (KJS::getUTCOffset):
     31        (KJS::getDSTOffsetSimple):
     32        (KJS::getDSTOffset):
     33        (KJS::localTimeToUTC):
     34        (KJS::UTCToLocalTime):
     35        (KJS::dateToMseconds):
     36        (KJS::msToTM):
     37        (KJS::isDST):
     38        * kjs/DateMath.h: Added.
     39        (KJS::):
     40        * kjs/date_object.cpp:
     41        (KJS::gmtoffset):
     42        (KJS::formatTime):
     43        (KJS::DateInstance::getTime):
     44        (KJS::DateInstance::getUTCTime):
     45        (KJS::DateProtoFunc::callAsFunction):
     46        (KJS::DateObjectImp::construct):
     47        (KJS::DateObjectFuncImp::callAsFunction):
     48        (KJS::parseDate):
     49        * kjs/testkjs.cpp:
     50        * os-win32/stdint.h:
     51
    1522006-10-02  Nikolas Zimmermann  <zimmermann@kde.org>
    253
  • trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r16632 r16780  
    224224                        </File>
    225225                        <File
     226                                RelativePath="..\..\kjs\DateMath.cpp"
     227                                >
     228                        </File>
     229                        <File
     230                                RelativePath="..\..\kjs\DateMath.h"
     231                                >
     232                        </File>
     233                        <File
    226234                                RelativePath="..\..\kjs\debugger.cpp"
    227235                                >
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r16621 r16780  
    261261                93F0B3AC09BB4DC00068FCE3 /* Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F0B3AA09BB4DC00068FCE3 /* Parser.h */; };
    262262                BCF655590A2049710038A194 /* MathExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF6553B0A2048DE0038A194 /* MathExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
     263                D212022A0AD4310D00ED79B6 /* DateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D21202280AD4310C00ED79B6 /* DateMath.cpp */; };
     264                D212022B0AD4310D00ED79B6 /* DateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateMath.h */; };
    263265                E195679609E7CF1200B89D13 /* UnicodeIcu.h in Headers */ = {isa = PBXBuildFile; fileRef = E195678F09E7CF1200B89D13 /* UnicodeIcu.h */; };
    264266                E195679809E7CF1200B89D13 /* Unicode.h in Headers */ = {isa = PBXBuildFile; fileRef = E195679409E7CF1200B89D13 /* Unicode.h */; };
     
    516518                93F1981A08245AAE001E9ABC /* keywords.table */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = text; path = keywords.table; sourceTree = "<group>"; tabWidth = 8; };
    517519                BCF6553B0A2048DE0038A194 /* MathExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MathExtras.h; sourceTree = "<group>"; };
     520                D21202280AD4310C00ED79B6 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; };
     521                D21202290AD4310C00ED79B6 /* DateMath.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateMath.h; sourceTree = "<group>"; };
    518522                E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = "<group>"; };
    519523                E195679409E7CF1200B89D13 /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = "<group>"; };
     
    851855                                F692A8550255597D01FF60F7 /* date_object.cpp */,
    852856                                F692A8560255597D01FF60F7 /* date_object.h */,
     857                                D21202280AD4310C00ED79B6 /* DateMath.cpp */,
     858                                D21202290AD4310C00ED79B6 /* DateMath.h */,
    853859                                F692A8580255597D01FF60F7 /* debugger.cpp */,
    854860                                F692A8590255597D01FF60F7 /* debugger.h */,
     
    11231129                                65C7A1740A8EAACB00FA37EA /* JSWrapperObject.h in Headers */,
    11241130                                93B6A0DF0AA64DA40076DE27 /* GetPtr.h in Headers */,
     1131                                D212022B0AD4310D00ED79B6 /* DateMath.h in Headers */,
    11251132                        );
    11261133                        runOnlyForDeploymentPostprocessing = 0;
     
    12271234                        isa = PBXProject;
    12281235                        buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
    1229                         compatibilityVersion = "Xcode 2.4";
    12301236                        hasScannedForEncodings = 1;
    12311237                        mainGroup = 0867D691FE84028FC02AAC07 /* JavaScriptCore */;
     
    12331239                        projectDirPath = "";
    12341240                        projectRoot = "";
    1235                         shouldCheckCompatibility = 1;
    12361241                        targets = (
    12371242                                932F5B3E0822A1C700736975 /* JavaScriptCore */,
     
    14121417                                65400C110A69BAF200509887 /* PropertyNameArray.cpp in Sources */,
    14131418                                65C7A1730A8EAACB00FA37EA /* JSWrapperObject.cpp in Sources */,
     1419                                D212022A0AD4310D00ED79B6 /* DateMath.cpp in Sources */,
    14141420                        );
    14151421                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/JavaScriptCore/kjs/date_object.cpp

    r16164 r16780  
    5252#include "error_object.h"
    5353#include "operations.h"
     54#include <DateMath.h>
    5455
    5556#include <wtf/MathExtras.h>
     
    5758
    5859#if PLATFORM(MAC)
    59 #include <CoreFoundation/CoreFoundation.h>
    60 #endif
     60    #include <CoreFoundation/CoreFoundation.h>
     61#endif
     62
     63namespace KJS {
     64
     65static double parseDate(const UString&);
     66static double timeClip(double);
    6167
    6268inline int gmtoffset(const tm& t)
     
    6470#if PLATFORM(WIN_OS)
    6571    // Time is supposed to be in the current timezone.
    66     // FIXME: Use undocumented _dstbias?
    67     return -(_timezone / 60 - (t.tm_isdst > 0 ? 60 : 0 )) * 60;
     72    return static_cast<int>(getUTCOffset()/1000.0);
    6873#else
    6974    return t.tm_gmtoff;
     
    7176}
    7277
    73 namespace KJS {
    7478
    7579/**
     
    9094    int id;
    9195};
    92 
    93 // some constants
    94 const double hoursPerDay = 24;
    95 const double minutesPerHour = 60;
    96 const double secondsPerMinute = 60;
    97 const double msPerSecond = 1000;
    98 const double msPerMinute = 60 * 1000;
    99 const double msPerHour = 60 * 60 * 1000;
    100 const double msPerDay = 24 * 60 * 60 * 1000;
    101 
    102 static const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    103 static const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    104 
    105 static double makeTime(tm *, double ms, bool utc);
    106 static double parseDate(const UString &);
    107 static double timeClip(double);
    108 static void millisecondsToTM(double milli, bool utc, tm *t);
    10996
    11097#if PLATFORM(MAC)
     
    197184    char buffer[100];
    198185    if (utc) {
    199         // FIXME: why not on windows?
    200 #if !PLATFORM(WIN_OS)
     186#if !PLATFORM(WIN_OS)   //win doesn't have the tm_gtoff member
    201187        ASSERT(t.tm_gmtoff == 0);
    202188#endif
     
    221207    }
    222208    return UString(buffer);
    223 }
    224 
    225 static int day(double t)
    226 {
    227     return int(floor(t / msPerDay));
    228 }
    229 
    230 static double dayFromYear(int year)
    231 {
    232     return 365.0 * (year - 1970)
    233         + floor((year - 1969) / 4.0)
    234         - floor((year - 1901) / 100.0)
    235         + floor((year - 1601) / 400.0);
    236 }
    237 
    238 // based on the rule for whether it's a leap year or not
    239 static int daysInYear(int year)
    240 {
    241     if (year % 4 != 0)
    242         return 365;
    243     if (year % 400 == 0)
    244         return 366;
    245     if (year % 100 == 0)
    246         return 365;
    247     return 366;
    248 }
    249 
    250 // time value of the start of a year
    251 static double timeFromYear(int year)
    252 {
    253     return msPerDay * dayFromYear(year);
    254 }
    255 
    256 // year determined by time value
    257 static int yearFromTime(double t)
    258 {
    259     // ### there must be an easier way
    260 
    261     // initial guess
    262     int y = 1970 + int(t / (365.25 * msPerDay));
    263 
    264     // adjustment
    265     if (timeFromYear(y) > t) {
    266         do
    267             --y;
    268         while (timeFromYear(y) > t);
    269     } else {
    270         while (timeFromYear(y + 1) < t)
    271             ++y;
    272     }
    273 
    274     return y;
    275 }
    276 
    277 // 0: Sunday, 1: Monday, etc.
    278 static int weekDay(double t)
    279 {
    280     int wd = (day(t) + 4) % 7;
    281     if (wd < 0)
    282         wd += 7;
    283     return wd;
    284209}
    285210
     
    369294        return false;
    370295   
    371     millisecondsToTM(milli, false, &t);
     296    msToTM(milli, false, t);
    372297    offset = gmtoffset(t);
    373298    return true;
     
    380305        return false;
    381306   
    382     millisecondsToTM(milli, true, &t);
     307    msToTM(milli, true, t);
    383308    return true;
    384309}
     
    391316   
    392317    tm t;
    393     millisecondsToTM(milli, false, &t);
     318    msToTM(milli, false, t);
    394319    offset = gmtoffset(t);
    395320    return true;
     
    410335    return minusOne < 0;
    411336}
    412 
    413 static void millisecondsToTM(double milli, bool utc, tm *t)
    414 {
    415   // check whether time value is outside time_t's usual range
    416   // make the necessary transformations if necessary
    417   static bool time_tIsSigned = isTime_tSigned();
    418   static double time_tMin = (time_tIsSigned ? - (double)(1ULL << (8 * sizeof(time_t) - 1)) : 0);
    419   static double time_tMax = (time_tIsSigned ? (1ULL << 8 * sizeof(time_t) - 1) - 1 : 2 * (double)(1ULL << 8 * sizeof(time_t) - 1) - 1);
    420   int realYearOffset = 0;
    421   double milliOffset = 0.0;
    422   double secs = floor(milli / msPerSecond);
    423 
    424   if (secs < time_tMin || secs > time_tMax) {
    425     // ### ugly and probably not very precise
    426     int realYear = yearFromTime(milli);
    427     int base = daysInYear(realYear) == 365 ? 2001 : 2000;
    428     milliOffset = timeFromYear(base) - timeFromYear(realYear);
    429     milli += milliOffset;
    430     realYearOffset = realYear - base;
    431   }
    432 
    433   time_t tv = (time_t) floor(milli / msPerSecond);
    434 
    435   *t = *(utc ? gmtime(&tv) : localtime(&tv));
    436   // We had an out of range year. Restore the year (plus/minus offset
    437   // found by calculating tm_year) and fix the week day calculation.
    438   if (realYearOffset != 0) {
    439     t->tm_year += realYearOffset;
    440     milli -= milliOffset;
    441     // Do our own weekday calculation. Use time zone offset to handle local time.
    442     double m = milli;
    443     if (!utc)
    444       m += gmtoffset(*t) * msPerSecond;
    445     t->tm_wday = weekDay(m);
    446   }
    447 }   
    448 
    449337
    450338// ------------------------------ DatePrototype -----------------------------
     
    576464
    577465  tm t;
    578   millisecondsToTM(milli, utc, &t);
     466  msToTM(milli, utc, t);
    579467
    580468  switch (id) {
     
    675563      id == SetMinutes || id == SetHours || id == SetDate ||
    676564      id == SetMonth || id == SetFullYear ) {
    677     result = jsNumber(makeTime(&t, ms, utc));
     565    result = jsNumber(dateToMseconds(&t, ms, utc));
    678566    thisDateObj->setInternalValue(result);
    679567  }
     
    762650      t.tm_isdst = -1;
    763651      double ms = (numArgs >= 7) ? roundValue(exec, args[6]) : 0;
    764       value = makeTime(&t, ms, false);
     652      value = dateToMseconds(&t, ms, false);
    765653    }
    766654  }
     
    815703    t.tm_sec = (n >= 6) ? args[5]->toInt32(exec) : 0;
    816704    double ms = (n >= 7) ? roundValue(exec, args[6]) : 0;
    817     return jsNumber(makeTime(&t, ms, true));
     705    return jsNumber(dateToMseconds(&t, ms, true));
    818706  }
    819707}
     
    853741    { "PDT", -420 }
    854742};
    855 
    856 static double makeTime(tm *t, double ms, bool utc)
    857 {
    858     int utcOffset;
    859     if (utc) {
    860         time_t zero = 0;
    861 #if PLATFORM(WIN_OS)
    862         // FIXME: not thread safe
    863         (void)localtime(&zero);
    864 #if COMPILER(BORLAND) || COMPILER(CYGWIN)
    865         utcOffset = - _timezone;
    866 #else
    867         utcOffset = - timezone;
    868 #endif
    869         t->tm_isdst = 0;
    870 #else
    871         tm t3;
    872         localtime_r(&zero, &t3);
    873         utcOffset = t3.tm_gmtoff;
    874         t->tm_isdst = t3.tm_isdst;
    875 #endif
    876     } else {
    877         utcOffset = 0;
    878         t->tm_isdst = -1;
    879     }
    880 
    881     double yearOffset = 0.0;
    882     if (t->tm_year < (1970 - 1900) || t->tm_year > (2038 - 1900)) {
    883         // we'll fool mktime() into believing that this year is within
    884         // its normal, portable range (1970-2038) by setting tm_year to
    885         // 2000 or 2001 and adding the difference in milliseconds later.
    886         // choice between offset will depend on whether the year is a
    887         // leap year or not.
    888         int y = t->tm_year + 1900;
    889         int baseYear = daysInYear(y) == 365 ? 2001 : 2000;
    890         double baseTime = timeFromYear(baseYear);
    891         yearOffset = timeFromYear(y) - baseTime;
    892         t->tm_year = baseYear - 1900;
    893     }
    894 
    895     // Determine whether DST is in effect. mktime() can't do this for us because
    896     // it doesn't know about ms and yearOffset.
    897     // NOTE: Casting values of large magnitude to time_t (long) will
    898     // produce incorrect results, but there's no other option when calling localtime_r().
    899     if (!utc) {
    900         time_t tval = mktime(t) + (time_t)((ms + yearOffset) / 1000); 
    901         tm t3 = *localtime(&tval); 
    902         t->tm_isdst = t3.tm_isdst; 
    903     }
    904 
    905     return (mktime(t) + utcOffset) * msPerSecond + ms + yearOffset;
    906 }
    907743
    908744inline static void skipSpacesAndComments(const char *&s)
     
    12341070        t.tm_hour = hour;
    12351071
    1236         // Use our makeTime() rather than mktime() as the latter can't handle the full year range.
    1237         return makeTime(&t, 0, false);
     1072        // Use our dateToMseconds() rather than mktime() as the latter can't handle the full year range.
     1073        return dateToMseconds(&t, 0, false);
    12381074    }
    12391075
  • trunk/JavaScriptCore/kjs/testkjs.cpp

    r15437 r16780  
    3232#include <math.h>
    3333#include <stdio.h>
     34
    3435#include <string.h>
    3536#if HAVE(SYS_TIME_H)
  • trunk/JavaScriptCore/os-win32/stdint.h

    r13717 r16780  
    2222#define STDINT_WIN32_H
    2323
     24#include <wtf/Platform.h>
     25
    2426/* This file emulates enough of stdint.h on Windows to make JavaScriptCore and WebCore compile. */
    25    
     27
    2628#if !PLATFORM(WIN_OS)
    2729#error "This stdint.h file should only be compiled under Windows"
Note: See TracChangeset for help on using the changeset viewer.