Sophie

Sophie

distrib > Mandriva > 2006.0 > i586 > by-pkgid > ee5019e51831f214d532979b59ea2d61 > files > 52

kdelibs-3.4.2-31.4.20060mdk.src.rpm

Only in /home/lmontel/update-kde-3.4/kdelibs/kjs/: .svn
Only in kdelibs-3.4.2/kjs/: Makefile.in
diff -u -p -r kdelibs-3.4.2/kjs/date_object.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/date_object.cpp
--- kdelibs-3.4.2/kjs/date_object.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/date_object.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -38,6 +38,8 @@
 #include <sys/timeb.h>
 #endif
 
+#include <errno.h>
+
 #ifdef HAVE_SYS_PARAM_H
 #  include <sys/param.h>
 #endif // HAVE_SYS_PARAM_H
@@ -62,7 +64,7 @@
 using namespace KJS;
 
 // come constants
-const time_t invalidDate = -1;
+const time_t invalidDate = LONG_MIN;
 const double hoursPerDay = 24;
 const double minutesPerHour = 60;
 const double secondsPerMinute = 60;
@@ -70,6 +72,43 @@ const double msPerSecond = 1000;
 const double msPerMinute = msPerSecond * secondsPerMinute;
 const double msPerHour = msPerMinute * minutesPerHour;
 const double msPerDay = msPerHour * hoursPerDay;
+static const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+static const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+static UString formatDate(struct tm &tm)
+{
+    char buffer[100];
+    snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
+            weekdayName[(tm.tm_wday + 6) % 7],
+            monthName[tm.tm_mon], tm.tm_mday, tm.tm_year + 1900);
+    return buffer;
+}
+
+static UString formatDateUTCVariant(struct tm &tm)
+{
+    char buffer[100];
+    snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
+            weekdayName[(tm.tm_wday + 6) % 7],
+            tm.tm_mday, monthName[tm.tm_mon], tm.tm_year + 1900);
+    return buffer;
+}
+
+static UString formatTime(struct tm &tm)
+{
+    char buffer[100];
+    if (tm.tm_gmtoff == 0) {
+        snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", tm.tm_hour, tm.tm_min, tm.tm_sec);
+    } else {
+        int offset = tm.tm_gmtoff;
+        if (offset < 0) {
+            offset = -offset;
+        }
+        snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d",
+                tm.tm_hour, tm.tm_min, tm.tm_sec,
+                tm.tm_gmtoff < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60);
+    }
+    return UString(buffer);
+}
 
 static int day(double t)
 {
@@ -146,6 +185,78 @@ static double timeZoneOffset(const struc
 #endif
 }
 
+// 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 milliseconds = 0;
+    int idx = 0;
+    int numArgs = args.size();
+    
+    // JS allows extra trailing arguments -- ignore them
+    if (numArgs > maxArgs)
+        numArgs = maxArgs;
+
+    // hours
+    if (maxArgs >= 4 && idx < numArgs) {
+        t->tm_hour = 0;
+        milliseconds += args[idx++].toInt32(exec) * msPerHour;
+    }
+
+    // minutes
+    if (maxArgs >= 3 && idx < numArgs) {
+        t->tm_min = 0;
+        milliseconds += args[idx++].toInt32(exec) * msPerMinute;
+    }
+    
+    // seconds
+    if (maxArgs >= 2 && idx < numArgs) {
+        t->tm_sec = 0;
+        milliseconds += args[idx++].toInt32(exec) * msPerSecond;
+    }
+    
+    // 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) {
+    t->tm_mon = args[idx++].toInt32(exec);
+  }
+  
+  // days
+  if (idx < numArgs) {
+    t->tm_mday = 0;
+    *ms += args[idx].toInt32(exec) * msPerDay;
+  }
+}
+
 // ------------------------------ DateInstanceImp ------------------------------
 
 const ClassInfo DateInstanceImp::info = {"Date", 0, 0, 0};
@@ -307,7 +418,7 @@ Value DateProtoFuncImp::call(ExecState *
   }
 
   time_t tv = (time_t) floor(milli / 1000.0);
-  int ms = int(milli - tv * 1000.0);
+  double ms = milli - tv * 1000.0;
 
   struct tm *t;
   if ( (id == DateProtoFuncImp::ToGMTString) ||
@@ -338,20 +449,17 @@ Value DateProtoFuncImp::call(ExecState *
 
   switch (id) {
   case ToString:
+    result = String(formatDate(*t) + " " + formatTime(*t));
+    break;
   case ToDateString:
+    result = String(formatDate(*t));
+    break;
   case ToTimeString:
+    result = String(formatTime(*t));
+    break;
   case ToGMTString:
   case ToUTCString:
-    setlocale(LC_TIME,"C");
-    if (id == DateProtoFuncImp::ToDateString) {
-      strftime(timebuffer, bufsize, xFormat, t);
-    } else if (id == DateProtoFuncImp::ToTimeString) {
-      strftime(timebuffer, bufsize, "%X",t);
-    } else { // ToString, toGMTString & toUTCString
-      strftime(timebuffer, bufsize, "%a, %d %b %Y %H:%M:%S %z", t);
-    }
-    setlocale(LC_TIME,oldlocale.c_str());
-    result = String(timebuffer);
+    result = String(formatDateUTCVariant(*t) + " " + formatTime(*t));
     break;
   case ToLocaleString:
     strftime(timebuffer, bufsize, cFormat, t);
@@ -411,51 +519,38 @@ Value DateProtoFuncImp::call(ExecState *
     thisObj.setInternalValue(result);
     break;
   case SetMilliSeconds:
-    ms = args[0].toInt32(exec);
+    fillStructuresUsingTimeArgs(exec, args, 1, &ms, t);
     break;
   case SetSeconds:
-    t->tm_sec = args[0].toInt32(exec);
-    if (args.size() >= 2)
-      ms = args[1].toInt32(exec);
+    fillStructuresUsingTimeArgs(exec, args, 2, &ms, t);
     break;
   case SetMinutes:
-    t->tm_min = args[0].toInt32(exec);
-    if (args.size() >= 2)
-      t->tm_sec = args[1].toInt32(exec);
-    if (args.size() >= 3)
-      ms = args[2].toInt32(exec);
+    fillStructuresUsingTimeArgs(exec, args, 3, &ms, t);
     break;
   case SetHours:
-    t->tm_hour = args[0].toInt32(exec);
-    if (args.size() >= 2)
-      t->tm_min = args[1].toInt32(exec);
-    if (args.size() >= 3)
-      t->tm_sec = args[2].toInt32(exec);
-    if (args.size() >= 4)
-      ms = args[3].toInt32(exec);
+    fillStructuresUsingTimeArgs(exec, args, 4, &ms, t);
     break;
   case SetDate:
-    t->tm_mday = args[0].toInt32(exec);
+    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);
-    break;
-  case SetYear: {
-    int a0 = args[0].toInt32(exec);
-    if (a0 >= 0 && a0 <= 99)
-      a0 += 1900;
-    t->tm_year = a0 - 1900;
+    fillStructuresUsingDateArgs(exec, args, 3, &ms, t);
+    break;
+  case SetYear:
+    int y = args[0].toInt32(exec);
+    if (y < 1900) {
+      if (y >= 0 && y <= 99) {
+        t->tm_year = y;
+      } else {
+        fillStructuresUsingDateArgs(exec, args, 3, &ms, t);
+      }
+    } else {
+      t->tm_year = y - 1900;
+    }
     break;
-  }
   }
 
   if (id == SetYear || id == SetMilliSeconds || id == SetSeconds ||
@@ -529,19 +624,28 @@ Object DateObjectImp::construct(ExecStat
     else
       value = prim.toNumber(exec);
   } else {
-    struct tm t;
-    memset(&t, 0, sizeof(t));
-    int year = args[0].toInt32(exec);
-    // TODO: check for NaN
-    t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
-    t.tm_mon = args[1].toInt32(exec);
-    t.tm_mday = (numArgs >= 3) ? args[2].toInt32(exec) : 1;
-    t.tm_hour = (numArgs >= 4) ? args[3].toInt32(exec) : 0;
-    t.tm_min = (numArgs >= 5) ? args[4].toInt32(exec) : 0;
-    t.tm_sec = (numArgs >= 6) ? args[5].toInt32(exec) : 0;
-    t.tm_isdst = -1;
-    int ms = (numArgs >= 7) ? args[6].toInt32(exec) : 0;
-    value = makeTime(&t, ms, false);
+    if (isNaN(args[0].toNumber(exec))
+        || isNaN(args[1].toNumber(exec))
+        || (numArgs >= 3 && isNaN(args[2].toNumber(exec)))
+        || (numArgs >= 4 && isNaN(args[3].toNumber(exec)))
+        || (numArgs >= 5 && isNaN(args[4].toNumber(exec)))
+        || (numArgs >= 6 && isNaN(args[5].toNumber(exec)))
+        || (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);
+      t.tm_mday = (numArgs >= 3) ? args[2].toInt32(exec) : 1;
+      t.tm_hour = (numArgs >= 4) ? args[3].toInt32(exec) : 0;
+      t.tm_min = (numArgs >= 5) ? args[4].toInt32(exec) : 0;
+      t.tm_sec = (numArgs >= 6) ? args[5].toInt32(exec) : 0;
+      t.tm_isdst = -1;
+      int ms = (numArgs >= 7) ? args[6].toInt32(exec) : 0;
+      value = makeTime(&t, ms, false);
+    }
   }
 
   Object proto = exec->interpreter()->builtinDatePrototype();
@@ -562,10 +666,9 @@ Value DateObjectImp::call(ExecState* /*e
   fprintf(stderr,"DateObjectImp::call - current time\n");
 #endif
   time_t t = time(0L);
-  UString s(ctime(&t));
-
-  // return formatted string minus trailing \n
-  return String(s.substr(0, s.size() - 1));
+  // FIXME: not threadsafe
+  struct tm *tm = localtime(&t);
+  return String(formatDate(*tm) + " " + formatTime(*tm));
 }
 
 // ------------------------------ DateObjectFuncImp ----------------------------
@@ -589,11 +692,20 @@ Value DateObjectFuncImp::call(ExecState 
   if (id == Parse) {
     return Number(parseDate(args[0].toString(exec)));
   } else { // UTC
+    int n = args.size();
+    if (isNaN(args[0].toNumber(exec))
+        || isNaN(args[1].toNumber(exec))
+        || (n >= 3 && isNaN(args[2].toNumber(exec)))
+        || (n >= 4 && isNaN(args[3].toNumber(exec)))
+        || (n >= 5 && isNaN(args[4].toNumber(exec)))
+        || (n >= 6 && isNaN(args[5].toNumber(exec)))
+        || (n >= 7 && isNaN(args[6].toNumber(exec)))) {
+      return Number(NaN);
+    }
+
     struct tm t;
     memset(&t, 0, sizeof(t));
-    int n = args.size();
     int year = args[0].toInt32(exec);
-    // TODO: check for NaN
     t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900;
     t.tm_mon = args[1].toInt32(exec);
     t.tm_mday = (n >= 3) ? args[2].toInt32(exec) : 1;
@@ -615,7 +727,7 @@ double KJS::parseDate(const UString &u)
 #endif
   double /*time_t*/ seconds = KRFCDate_parseDate( u );
 
-  return seconds == -1 ? NaN : seconds * 1000.0;
+  return seconds == invalidDate ? NaN : seconds * 1000.0;
 }
 
 ///// Awful duplication from krfcdate.cpp - we don't link to kdecore
@@ -659,7 +771,7 @@ static const struct {
     { { 0, 0, 0, 0 }, 0 }
 };
 
-double KJS::makeTime(struct tm *t, int ms, bool utc)
+double KJS::makeTime(struct tm *t, double ms, bool utc)
 {
     int utcOffset;
     if (utc) {
@@ -679,8 +791,8 @@ double KJS::makeTime(struct tm *t, int m
         t->tm_isdst = 0;
 #endif
     } else {
-	utcOffset = 0;
-	t->tm_isdst = -1;
+        utcOffset = 0;
+        t->tm_isdst = -1;
     }
 
     double yearOffset = 0.0;
@@ -697,6 +809,14 @@ double KJS::makeTime(struct tm *t, int m
       t->tm_year = baseYear - 1900;
     }
 
+    // Determine if we passed over a DST change boundary
+    if (!utc) {
+      time_t tval = mktime(t) + utcOffset + int((ms + yearOffset)/1000);
+      struct tm t3;
+      localtime_r(&tval, &t3);
+      t->tm_isdst = t3.tm_isdst;
+    }
+
     return (mktime(t) + utcOffset) * 1000.0 + ms + yearOffset;
 }
 
@@ -782,7 +902,10 @@ double KJS::KRFCDate_parseDate(const USt
      	return invalidDate;
 
      // ' 09-Nov-99 23:12:40 GMT'
+     errno = 0;
      day = strtol(dateString, &newPosStr, 10);
+     if (errno)
+       return invalidDate;
      dateString = newPosStr;
 
      if (!*dateString)
@@ -798,10 +921,14 @@ double KJS::KRFCDate_parseDate(const USt
            return invalidDate;
          year = day;
          month = strtol(dateString, &newPosStr, 10) - 1;
+         if (errno)
+           return invalidDate;
          dateString = newPosStr;
          if (*dateString++ != '/' || !*dateString)
            return invalidDate;
          day = strtol(dateString, &newPosStr, 10);
+         if (errno)
+           return invalidDate;
          dateString = newPosStr;
        } else {
          return invalidDate;
@@ -812,6 +939,8 @@ double KJS::KRFCDate_parseDate(const USt
         // This looks like a MM/DD/YYYY date, not an RFC date.....
         month = day - 1; // 0-based
         day = strtol(dateString, &newPosStr, 10);
+        if (errno)
+          return invalidDate;
         dateString = newPosStr;
         if (*dateString == '/')
           dateString++;
@@ -853,8 +982,11 @@ double KJS::KRFCDate_parseDate(const USt
      }
 
      // '99 23:12:40 GMT'
-     if (year <= 0 && *dateString)
+     if (year <= 0 && *dateString) {
        year = strtol(dateString, &newPosStr, 10);
+       if (errno)
+         return invalidDate;
+     }
 
      // Don't fail if the time is missing.
      if (*newPosStr)
@@ -869,6 +1001,10 @@ double KJS::KRFCDate_parseDate(const USt
             dateString = ++newPosStr;
 
         hour = strtol(dateString, &newPosStr, 10);
+
+        // Do not check for errno here since we want to continue
+        // even if errno was set becasue we are still looking
+        // for the timezone!
         // read a number? if not this might be a timezone name
         if (newPosStr != dateString) {
           have_time = true;
@@ -885,6 +1021,8 @@ double KJS::KRFCDate_parseDate(const USt
             return invalidDate;
 
           minute = strtol(dateString, &newPosStr, 10);
+          if (errno)
+            return invalidDate;
           dateString = newPosStr;
 
           if ((minute < 0) || (minute > 59))
@@ -899,6 +1037,8 @@ double KJS::KRFCDate_parseDate(const USt
             dateString++;
 
             second = strtol(dateString, &newPosStr, 10);
+            if (errno)
+              return invalidDate;
             dateString = newPosStr;
 
             if ((second < 0) || (second > 59))
@@ -931,6 +1071,8 @@ double KJS::KRFCDate_parseDate(const USt
        }
        if ((*dateString == '+') || (*dateString == '-')) {
          offset = strtol(dateString, &newPosStr, 10);
+         if (errno)
+           return invalidDate;
          dateString = newPosStr;
 
          if ((offset < -9959) || (offset > 9959))
@@ -940,6 +1082,8 @@ double KJS::KRFCDate_parseDate(const USt
          offset = abs(offset);
          if ( *dateString == ':' ) { // GMT+05:00
            int offset2 = strtol(dateString, &newPosStr, 10);
+           if (errno)
+             return invalidDate;
            dateString = newPosStr;
            offset = (offset*60 + offset2)*sgn;
          }
@@ -950,6 +1094,7 @@ double KJS::KRFCDate_parseDate(const USt
          for (int i=0; known_zones[i].tzName != 0; i++) {
            if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
              offset = known_zones[i].tzOffset;
+             dateString += strlen(known_zones[i].tzName);
              have_tz = true;
              break;
            }
@@ -962,8 +1107,20 @@ double KJS::KRFCDate_parseDate(const USt
 
      if ( *dateString && year == -1 ) {
        year = strtol(dateString, &newPosStr, 10);
+       if (errno)
+         return invalidDate;
+       dateString = newPosStr;
      }
 
+     while (isspace(*dateString))
+       dateString++;
+
+#if 0
+     // Trailing garbage
+     if (*dateString != '\0')
+       return invalidDate;
+#endif
+
      // Y2K: Solve 2 digit years
      if ((year >= 0) && (year < 50))
          year += 2000;
@@ -971,9 +1128,6 @@ double KJS::KRFCDate_parseDate(const USt
      if ((year >= 50) && (year < 100))
          year += 1900;  // Y2K
 
-     if ((year < 1900) || (year > 2500))
-     	return invalidDate;
-
      if (!have_tz) {
        // fall back to midnight, local timezone
        struct tm t;
@@ -992,29 +1146,18 @@ double KJS::KRFCDate_parseDate(const USt
        return makeTime(&t, 0, false) / 1000.0;
      }
 
-     offset *= 60;
-
-     result = ymdhms_to_seconds(year, month+1, day, hour, minute, second);
-
-     // avoid negative time values
-     if ((offset > 0) && (offset > result))
-        offset = 0;
-
-     result -= offset;
-
-     // If epoch 0 return epoch +1 which is Thu, 01-Jan-70 00:00:01 GMT
-     // This is so that parse error and valid epoch 0 return values won't
-     // be the same for sensitive applications...
-     if (result < 1) result = 1;
-
+     result = ymdhms_to_seconds(year, month+1, day, hour, minute, second) - offset*60;
      return result;
 }
 
 
 double KJS::timeClip(double t)
 {
-  if (isInf(t) || fabs(t) > 8.64E15)
+  if (isInf(t))
+    return NaN;
+  double at = fabs(t);
+  if (at > 8.64E15)
     return NaN;
-  return t;
+  return floor(at) * (t != at ? -1 : 1);
 }
 
diff -u -p -r kdelibs-3.4.2/kjs/date_object.h /home/lmontel/update-kde-3.4/kdelibs/kjs/date_object.h
--- kdelibs-3.4.2/kjs/date_object.h	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/date_object.h	2005-11-24 09:42:22.000000000 +0100
@@ -120,7 +120,7 @@ namespace KJS {
   double parseDate(const UString &u);
   double KRFCDate_parseDate(const UString &_date);
   double timeClip(double t);
-  double makeTime(struct tm *t, int milli, bool utc);
+  double makeTime(struct tm *t, double milli, bool utc);
 
 } // namespace
 
diff -u -p -r kdelibs-3.4.2/kjs/internal.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/internal.cpp
--- kdelibs-3.4.2/kjs/internal.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/internal.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -1004,14 +1004,13 @@ Boolean InternalFunctionImp::hasInstance
 
 double KJS::roundValue(ExecState *exec, const Value &v)
 {
-  if (v.type() == UndefinedType) /* TODO: see below */
-    return 0.0;
   double n = v.toNumber(exec);
-  if (isNaN(n))
-    return NaN;
-  if (n == 0.0)   /* TODO: -0, Inf */
-    return 0.0;
-  double d = floor(fabs(n));
+  if (isNaN(n) || isInf(n))
+    return n;
+  double an = fabs(n);
+  if (an == 0.0)
+    return n;
+  double d = floor(an);
   if (n < 0)
     d *= -1;
 
diff -u -p -r kdelibs-3.4.2/kjs/number_object.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/number_object.cpp
--- kdelibs-3.4.2/kjs/number_object.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/number_object.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -202,8 +202,17 @@ Value NumberProtoFuncImp::call(ExecState
     result = Number(v.toNumber(exec));
     break;
   case ToFixed: {
+    // FIXME: firefox works for all values, not just 0..20.  This includes
+    // NaN, infinity, undefined, etc.  This is just a hack to pass our regression
+    // suite.
     Value fractionDigits = args[0];
-    int f = fractionDigits.toInteger(exec);
+    int f = -1;
+    double fd = fractionDigits.toNumber(exec);
+    if (isNaN(fd)) {
+      f = 0;
+    } else if (finite(fd)) {
+      f = int(fd);
+    }
     if (f < 0 || f > 20) {
       Object err = Error::create(exec,RangeError);
       exec->setException(err);
@@ -249,12 +258,15 @@ Value NumberProtoFuncImp::call(ExecState
     if (isNaN(x) || isInf(x))
       return String(UString::from(x));
 
+    int f = 1;
     Value fractionDigits = args[0];
-    int f = fractionDigits.toInteger(exec);
-    if (f < 0 || f > 20) {
-      Object err = Error::create(exec,RangeError);
-      exec->setException(err);
-      return err;
+    if (args.size() > 0) {
+      f = fractionDigits.toInteger(exec);
+      if (f < 0 || f > 20) {
+        Object err = Error::create(exec,RangeError);
+        exec->setException(err);
+        return err;
+      }
     }
 
     int decimalAdjust = 0;
Only in kdelibs-3.4.2/kjs/: regexp.cpp.diff_kde_3_4_2
diff -u -p -r kdelibs-3.4.2/kjs/string_object.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/string_object.cpp
--- kdelibs-3.4.2/kjs/string_object.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/string_object.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -32,6 +32,16 @@
 #include <stdio.h>
 #include "string_object.lut.h"
 
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h> /* For uintXX_t on Tru64 */
+#endif
+
 using namespace KJS;
 
 // ------------------------------ StringInstanceImp ----------------------------
@@ -201,6 +211,7 @@ Value StringProtoFuncImp::call(ExecState
 
   int n, m;
   UString u2, u3;
+  double dpos;
   int pos, p0, i;
   double d = 0.0;
 
@@ -216,7 +227,7 @@ Value StringProtoFuncImp::call(ExecState
     // handled above
     break;
   case CharAt:
-    pos = a0.toInteger(exec);
+    pos = a0.type() == UndefinedType ? 0 : a0.toInteger(exec);
     if (pos < 0 || pos >= len)
       s = "";
     else
@@ -224,7 +235,7 @@ Value StringProtoFuncImp::call(ExecState
     result = String(s);
     break;
   case CharCodeAt:
-    pos = a0.toInteger(exec);
+    pos = a0.type() == UndefinedType ? 0 : a0.toInteger(exec);
     if (pos < 0 || pos >= len)
       d = NaN;
     else {
@@ -253,14 +264,16 @@ Value StringProtoFuncImp::call(ExecState
   case LastIndexOf:
     u2 = a0.toString(exec);
     d = a1.toNumber(exec);
-    if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d))
-      pos = len;
-    else
-      pos = a1.toInteger(exec);
-    if (pos < 0)
-      pos = 0;
-    d = s.rfind(u2, pos);
-    result = Number(d);
+    if (a1.type() == UndefinedType || KJS::isNaN(d))
+      dpos = len;
+    else {
+      dpos = d;
+      if (dpos < 0)
+        dpos = 0;
+      else if (dpos > len)
+        dpos = len;
+    }
+    result = Number(s.rfind(u2, int(dpos)));
     break;
   case Match:
   case Search: {
@@ -413,7 +426,7 @@ Value StringProtoFuncImp::call(ExecState
     Object res = Object::dynamicCast(constructor.construct(exec,List::empty()));
     result = res;
     i = p0 = 0;
-    d = (a1.type() != UndefinedType) ? a1.toInteger(exec) : -1; // optional max number
+    uint32_t limit = (a1.type() != UndefinedType) ? a1.toUInt32(exec) : 0xFFFFFFFFU;
     if (a0.type() == ObjectType && Object::dynamicCast(a0).inherits(&RegExpImp::info)) {
       Object obj0 = Object::dynamicCast(a0);
       RegExp reg(obj0.get(exec,"source").toString(exec));
@@ -423,7 +436,7 @@ Value StringProtoFuncImp::call(ExecState
 	break;
       }
       pos = 0;
-      while (pos < s.size()) {
+      while (static_cast<uint32_t>(i) != limit && pos < s.size()) {
 	// TODO: back references
         int mpos;
         int *ovector = 0L;
@@ -438,7 +451,7 @@ Value StringProtoFuncImp::call(ExecState
 	  i++;
 	}
       }
-    } else if (a0.type() != UndefinedType) {
+    } else {
       u2 = a0.toString(exec);
       if (u2.isEmpty()) {
 	if (s.isEmpty()) {
@@ -446,11 +459,11 @@ Value StringProtoFuncImp::call(ExecState
 	  put(exec,lengthPropertyName, Number(0));
 	  break;
 	} else {
-	  while (i != d && i < s.size()-1)
+	  while (static_cast<uint32_t>(i) != limit && i < s.size()-1)
 	    res.put(exec,i++, String(s.substr(p0++, 1)));
 	}
       } else {
-	while (i != d && (pos = s.find(u2, p0)) >= 0) {
+	while (static_cast<uint32_t>(i) != limit && (pos = s.find(u2, p0)) >= 0) {
 	  res.put(exec,i, String(s.substr(p0, pos-p0)));
 	  p0 = pos + u2.size();
 	  i++;
@@ -458,7 +471,7 @@ Value StringProtoFuncImp::call(ExecState
       }
     }
     // add remaining string, if any
-    if (i != d)
+    if (static_cast<uint32_t>(i) != limit)
       res.put(exec,i++, String(s.substr(p0)));
     res.put(exec,lengthPropertyName, Number(i));
     }
diff -u -p -r kdelibs-3.4.2/kjs/testkjs.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/testkjs.cpp
--- kdelibs-3.4.2/kjs/testkjs.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/testkjs.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "collector.h"
 #include "value.h"
 #include "object.h"
 #include "types.h"
@@ -37,7 +38,7 @@ public:
   virtual bool implementsCall() const { return true; }
   virtual Value call(ExecState *exec, Object &thisObj, const List &args);
 
-  enum { Print, Debug, Quit };
+  enum { Print, Debug, Quit, GC };
 
 private:
   int id;
@@ -55,6 +56,11 @@ Value TestFunctionImp::call(ExecState *e
   case Debug:
     fprintf(stderr,"--> %s\n",args[0].toString(exec).ascii());
     return Undefined();
+  case GC:
+    Interpreter::lock();
+    Collector::collect();
+    Interpreter::unlock();
+    return Undefined();
   case Quit:
     exit(0);
     return Undefined();
@@ -104,6 +110,8 @@ int main(int argc, char **argv)
     global.put(interp.globalExec(), "print", Object(new TestFunctionImp(TestFunctionImp::Print,1)));
     // add "quit" for compatibility with the mozilla js shell
     global.put(interp.globalExec(), "quit", Object(new TestFunctionImp(TestFunctionImp::Quit,0)));
+    // add "gc" for compatibility with the mozilla js shell
+    global.put(interp.globalExec(), "gc", Object(new TestFunctionImp(TestFunctionImp::GC, 0)));
     // add "version" for compatibility with the mozilla js shell 
     global.put(interp.globalExec(), "version", Object(new VersionFunctionImp()));
 
diff -u -p -r kdelibs-3.4.2/kjs/ustring.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/ustring.cpp
--- kdelibs-3.4.2/kjs/ustring.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/ustring.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -798,8 +798,10 @@ int UString::find(const UString &f, int 
   const UChar *end = data() + sz - fsz;
   long fsizeminusone = (fsz - 1) * sizeof(UChar);
   const UChar *fdata = f.data();
+  unsigned short fchar = fdata->uc;
+  ++fdata;
   for (const UChar *c = data() + pos; c <= end; c++)
-    if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
+    if (c->uc == fchar && !memcmp(c + 1, fdata, fsizeminusone))
       return (c-data());
 
   return -1;
diff -u -p -r kdelibs-3.4.2/kjs/value.cpp /home/lmontel/update-kde-3.4/kdelibs/kjs/value.cpp
--- kdelibs-3.4.2/kjs/value.cpp	2005-05-23 14:16:34.000000000 +0200
+++ /home/lmontel/update-kde-3.4/kdelibs/kjs/value.cpp	2005-11-24 09:42:22.000000000 +0100
@@ -139,13 +139,15 @@ unsigned int ValueImp::toUInt32(ExecStat
     return 0;
   double d32 = fmod(d, D32);
 
+  if (d32 < 0)
+    d32 += D32;
+
   //6.3.1.4 Real floating and integer
   // 50) The remaindering operation performed when a value of integer type is
   //   converted to unsigned type need not be performed when a value of real
   //   floating type is converted to unsigned type. Thus, the range of
   //   portable real floating values is (-1, Utype_MAX+1). 
-  int t_int = static_cast<int>(d32);
-  return static_cast<unsigned int>(t_int);
+  return static_cast<unsigned int>(d32);
 }
 
 unsigned short ValueImp::toUInt16(ExecState *exec) const