[webkit-changes] cvs commit: JavaScriptCore/kjs date_object.cpp

Geoffrey ggaren at opensource.apple.com
Wed Sep 7 16:27:28 PDT 2005


ggaren      05/09/07 16:27:28

  Modified:    .        ChangeLog
               kjs      date_object.cpp
  Log:
          -fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4781
          Date.setMonth fails with big values due to overflow
  
          Reviewed by darin.
  
          * kjs/date_object.cpp:
          (timetUsingCF): for consistency, changed return statement to invalidDate instead of LONG_MAX
          (KJS::fillStructuresUsingTimeArgs): modified for readability
          (KJS::fillStructuresUsingDateArgs): new function analogous to fillStructuresUsingTimeArgs
          (KJS::DateProtoFuncImp::callAsFunction): modified to use fillStructuresUsingDateArgs
          (KJS::DateObjectImp::construct): moved variable declaration to proper scope
          (KJS::DateObjectFuncImp::callAsFunction): moved variable declaration to proper scope
  
  Revision  Changes    Path
  1.818     +15 -0     JavaScriptCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/ChangeLog,v
  retrieving revision 1.817
  retrieving revision 1.818
  diff -u -r1.817 -r1.818
  --- ChangeLog	7 Sep 2005 22:08:54 -0000	1.817
  +++ ChangeLog	7 Sep 2005 23:27:27 -0000	1.818
  @@ -1,4 +1,19 @@
   2005-09-07  Geoffrey Garen  <ggaren at apple.com>
  +
  +        -fixed http://bugzilla.opendarwin.org/show_bug.cgi?id=4781
  +        Date.setMonth fails with big values due to overflow
  +
  +        Reviewed by darin.
  +
  +        * kjs/date_object.cpp:
  +        (timetUsingCF): for consistency, changed return statement to invalidDate instead of LONG_MAX
  +        (KJS::fillStructuresUsingTimeArgs): modified for readability
  +        (KJS::fillStructuresUsingDateArgs): new function analogous to fillStructuresUsingTimeArgs
  +        (KJS::DateProtoFuncImp::callAsFunction): modified to use fillStructuresUsingDateArgs
  +        (KJS::DateObjectImp::construct): moved variable declaration to proper scope
  +        (KJS::DateObjectFuncImp::callAsFunction): moved variable declaration to proper scope
  +
  +2005-09-07  Geoffrey Garen  <ggaren at apple.com>
           -updated expected test results to reflect fix for 
           http://bugzilla.opendarwin.org/show_bug.cgi?id=4698
           kjs does not allow named functions in function expressions
  
  
  
  1.55      +71 -30    JavaScriptCore/kjs/date_object.cpp
  
  Index: date_object.cpp
  ===================================================================
  RCS file: /cvs/root/JavaScriptCore/kjs/date_object.cpp,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- date_object.cpp	4 Sep 2005 06:21:54 -0000	1.54
  +++ date_object.cpp	7 Sep 2005 23:27:28 -0000	1.55
  @@ -201,7 +201,7 @@
   
       CFTimeInterval interval = absoluteTime + kCFAbsoluteTimeIntervalSince1970;
       if (interval > LONG_MAX) {
  -        interval = LONG_MAX;
  +        return invalidDate;
       }
   
       return (time_t) interval;
  @@ -403,34 +403,81 @@
   #endif
   }
   
  -static double timeFromArgs(ExecState *exec, const List &args, int maxArgs, double ms, struct tm *t)
  +// Converts a list of arguments sent to a Date member function into milliseconds, updating
  +// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
  +//
  +// Format of member function: f([hour,] [min,] [sec,] [ms])
  +static void fillStructuresUsingTimeArgs(ExecState *exec, const List &args, int maxArgs, double *ms, struct tm *t)
   {
  -    double result = 0;
  +    double milliseconds = 0;
       int idx = 0;
       int numArgs = args.size();
       
  -    // process up to max_args arguments
  +    // JS allows extra trailing arguments -- ignore them
       if (numArgs > maxArgs)
           numArgs = maxArgs;
  +
       // hours
       if (maxArgs >= 4 && idx < numArgs) {
           t->tm_hour = 0;
  -        result = args[idx++]->toInt32(exec) * msPerHour;
  +        milliseconds += args[idx++]->toInt32(exec) * msPerHour;
       }
  +
       // minutes
       if (maxArgs >= 3 && idx < numArgs) {
           t->tm_min = 0;
  -        result += args[idx++]->toInt32(exec) * msPerMinute;
  +        milliseconds += args[idx++]->toInt32(exec) * msPerMinute;
       }
  +    
       // seconds
       if (maxArgs >= 2 && idx < numArgs) {
           t->tm_sec = 0;
  -        result += args[idx++]->toInt32(exec) * msPerSecond;
  +        milliseconds += args[idx++]->toInt32(exec) * msPerSecond;
       }
  -    // read ms from args if present or add the old value
  -    result += idx < numArgs ? roundValue(exec, args[idx]) : ms;
  -            
  -    return result;
  +    
  +    // milliseconds
  +    if (idx < numArgs) {
  +        milliseconds += roundValue(exec, args[idx]);
  +    } else {
  +        milliseconds += *ms;
  +    }
  +    
  +    *ms = milliseconds;
  +}
  +
  +// Converts a list of arguments sent to a Date member function into years, months, and milliseconds, updating
  +// ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
  +//
  +// Format of member function: f([years,] [months,] [days])
  +static void fillStructuresUsingDateArgs(ExecState *exec, const List &args, int maxArgs, double *ms, struct tm *t)
  +{
  +  int idx = 0;
  +  int numArgs = args.size();
  +  
  +  // JS allows extra trailing arguments -- ignore them
  +  if (numArgs > maxArgs)
  +    numArgs = maxArgs;
  +  
  +  // years
  +  if (maxArgs >= 3 && idx < numArgs) {
  +    t->tm_year = args[idx++]->toInt32(exec) - 1900;
  +  }
  +  
  +  // months
  +  if (maxArgs >= 2 && idx < numArgs) {
  +    int months = args[idx++]->toInt32(exec);
  +
  +    // t->tm_year must hold the bulk of the data to avoid overflow when converting
  +    // to a CFGregorianDate. (CFGregorianDate.month is an SInt8; CFGregorianDate.year is an SInt32.)
  +    t->tm_year += months / 12;
  +    t->tm_mon = months % 12;
  +  }
  +  
  +  // days
  +  if (idx < numArgs) {
  +    t->tm_mday = 0;
  +    *ms += args[idx]->toInt32(exec) * msPerDay;
  +  }
   }
   
   // ------------------------------ DateInstanceImp ------------------------------
  @@ -722,32 +769,25 @@
       thisObj->setInternalValue(result);
       break;
     case SetMilliSeconds:
  -    ms = roundValue(exec, args[0]);
  +    fillStructuresUsingTimeArgs(exec, args, 1, &ms, t);
       break;
     case SetSeconds:
  -    ms = timeFromArgs(exec, args, 2, ms, t);
  +    fillStructuresUsingTimeArgs(exec, args, 2, &ms, t);
       break;
     case SetMinutes:
  -    ms = timeFromArgs(exec, args, 3, ms, t);
  +    fillStructuresUsingTimeArgs(exec, args, 3, &ms, t);
       break;
     case SetHours:
  -    ms = timeFromArgs(exec, args, 4, ms, t);
  +    fillStructuresUsingTimeArgs(exec, args, 4, &ms, t);
       break;
     case SetDate:
  -      t->tm_mday = 0;
  -      ms += args[0]->toInt32(exec) * msPerDay;
  -      break;
  +    fillStructuresUsingDateArgs(exec, args, 1, &ms, t);
  +    break;
     case SetMonth:
  -    t->tm_mon = args[0]->toInt32(exec);
  -    if (args.size() >= 2)
  -      t->tm_mday = args[1]->toInt32(exec);
  +    fillStructuresUsingDateArgs(exec, args, 2, &ms, t);    
       break;
     case SetFullYear:
  -    t->tm_year = args[0]->toInt32(exec) - 1900;
  -    if (args.size() >= 2)
  -      t->tm_mon = args[1]->toInt32(exec);
  -    if (args.size() >= 3)
  -      t->tm_mday = args[2]->toInt32(exec);
  +    fillStructuresUsingDateArgs(exec, args, 3, &ms, t);
       break;
     case SetYear:
       t->tm_year = args[0]->toInt32(exec) >= 1900 ? args[0]->toInt32(exec) - 1900 : args[0]->toInt32(exec);
  @@ -822,8 +862,6 @@
         else
             value = args[0]->toPrimitive(exec)->toNumber(exec);
     } else {
  -    struct tm t;
  -    memset(&t, 0, sizeof(t));
       if (isNaN(args[0]->toNumber(exec))
           || isNaN(args[1]->toNumber(exec))
           || (numArgs >= 3 && isNaN(args[2]->toNumber(exec)))
  @@ -833,6 +871,8 @@
           || (numArgs >= 7 && isNaN(args[6]->toNumber(exec)))) {
         value = NaN;
       } else {
  +      struct tm t;
  +      memset(&t, 0, sizeof(t));
         int year = args[0]->toInt32(exec);
         t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
         t.tm_mon = args[1]->toInt32(exec);
  @@ -892,8 +932,6 @@
       return Number(parseDate(args[0]->toString(exec)));
     }
     else { // UTC
  -    struct tm t;
  -    memset(&t, 0, sizeof(t));
       int n = args.size();
       if (isNaN(args[0]->toNumber(exec))
           || isNaN(args[1]->toNumber(exec))
  @@ -904,6 +942,9 @@
           || (n >= 7 && isNaN(args[6]->toNumber(exec)))) {
         return Number(NaN);
       }
  +
  +    struct tm t;
  +    memset(&t, 0, sizeof(t));
       int year = args[0]->toInt32(exec);
       t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
       t.tm_mon = args[1]->toInt32(exec);
  
  
  



More information about the webkit-changes mailing list