Author: j...@google.com
Date: Mon Jun  1 22:59:06 2009
New Revision: 5490

Modified:
    trunk/user/super/com/google/gwt/emul/java/util/Date.java
    trunk/user/test/com/google/gwt/emultest/java/util/DateTest.java

Log:
two changes to java.util.Date in an effort to track down a very intermittent
failure on IE.  IE doesn't provide useful stack traces for JS-initiated
exceptions, so all we know is that jsdate is uninitialized or not an object
at some point when it is dereferenced.  The changes are:
  - use a JSO field storing the JS Date object rather than
    making an expando on the underlying object (which
    couldn't ever work in hosted mode, but since this is a
    JRE emulation class it didn't have to)
  - add checks before each dereference of jsdate to see if it has been  
mangled;
    if so throws a Java exception so we can get a good stack trace.

This does add some overhead, but it shouldn't be too bad.  This is a  
temporary
change that will be removed once the cause is found.

Patch by: jat
Review by: amitmanjhi, scottb


Modified: trunk/user/super/com/google/gwt/emul/java/util/Date.java
==============================================================================
--- trunk/user/super/com/google/gwt/emul/java/util/Date.java    (original)
+++ trunk/user/super/com/google/gwt/emul/java/util/Date.java    Mon Jun  1  
22:59:06 2009
@@ -15,12 +15,21 @@
   */
  package java.util;

+import com.google.gwt.core.client.JavaScriptObject;
+
  import java.io.Serializable;

  /**
   * Represents a date and time.
   */
  public class Date implements Cloneable, Comparable<Date>, Serializable {
+
+  /**
+   * JavaScript Date instance.
+   */
+  @SuppressWarnings("unused") // used from JSNI
+  private JavaScriptObject jsdate;
+
    /**
     * Used only by toString().
     */
@@ -88,6 +97,16 @@
      return isNaN(d) ? -1 : d;
    }-*/;

+  /**
+   * Throw an exception if jsdate is not an object.
+   *
+   * @param val
+   */
+  @SuppressWarnings("unused") // called by JSNI
+  private static void throwJsDateException(String val) {
+    throw new IllegalStateException("jsdate is " + val);
+  }
+
    private static native double utc0(int year, int month, int date, int hrs,
        int min, int sec) /*-{
      return Date.UTC(year + 1900, month, date, hrs, min, sec);
@@ -147,27 +166,33 @@
    }

    public native int getDate() /*-{
-    return this.jsdate.getDate();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getDate();
    }-*/;

    public native int getDay() /*-{
-    return this.jsdate.getDay();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getDay();
    }-*/;

    public native int getHours() /*-{
-    return this.jsdate.getHours();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getHours();
    }-*/;

    public native int getMinutes() /*-{
-    return this.jsdate.getMinutes();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getMinutes();
    }-*/;

    public native int getMonth() /*-{
-    return this.jsdate.getMonth();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getMonth();
    }-*/;

    public native int getSeconds() /*-{
-    return this.jsdate.getSeconds();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getSeconds();
    }-*/;

    public long getTime() {
@@ -175,11 +200,13 @@
    }

    public native int getTimezoneOffset() /*-{
-    return this.jsdate.getTimezoneOffset();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getTimezoneOffset();
    }-*/;

    public native int getYear() /*-{
-    return this.jsdate.getFullYear()-1900;
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getFullYear()-1900;
    }-*/;

    @Override
@@ -188,23 +215,28 @@
    }

    public native void setDate(int date) /*-{
-    this.jsdate.setDate(date);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setDate(date);
    }-*/;

    public native void setHours(int hours) /*-{
-    this.jsdate.setHours(hours);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setHours(hours);
    }-*/;

    public native void setMinutes(int minutes) /*-{
-    this.jsdate.setMinutes(minutes);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setMinutes(minutes);
    }-*/;

    public native void setMonth(int month) /*-{
-    this.jsdate.setMonth(month);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setMonth(month);
    }-*/;

    public native void setSeconds(int seconds) /*-{
-    this.jsdate.setSeconds(seconds);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setSeconds(seconds);
    }-*/;

    public void setTime(long time) {
@@ -212,14 +244,16 @@
    }

    public native void setYear(int year) /*-{
-    this.jsdate.setFullYear(year + 1900);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setFullYear(year + 1900);
    }-*/;

    public native String toGMTString() /*-{
-    var d = this.jsdate;
+    th...@java.util.date::checkJsDate()();
+    var d = th...@java.util.date::jsdate;
      var padTwo = @java.util.Date::padTwo(I);
      var month =
-        @java.util.Date::monthToString(I)(this.jsdate.getUTCMonth());
+         
@java.util.Date::monthToString(I)(th...@java.util.date::jsdate.getUTCMonth());

      return d.getUTCDate() + " " +
          month + " " +
@@ -231,17 +265,19 @@
    }-*/;

    public native String toLocaleString() /*-{
-    return this.jsdate.toLocaleString();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.toLocaleString();
    }-*/;

    @Override
    public native String toString() /*-{
-    var d = this.jsdate;
+    th...@java.util.date::checkJsDate()();
+    var d = th...@java.util.date::jsdate;
      var padTwo = @java.util.Date::padTwo(I);
      var day =
-        @java.util.Date::dayToString(I)(this.jsdate.getDay());
+        @java.util.Date::dayToString(I)(d.getDay());
      var month =
-        @java.util.Date::monthToString(I)(this.jsdate.getMonth());
+        @java.util.Date::monthToString(I)(d.getMonth());

      // Compute timezone offset. The value that getTimezoneOffset returns is
      // backwards for the transformation that we want.
@@ -259,26 +295,41 @@
          + " " + d.getFullYear();
    }-*/;

+  /**
+   *  Check that jsdate is valid and throw an exception if not.
+   */
+  @SuppressWarnings("unused") // called by JSNI
+  private native void checkJsDate() /*-{
+    if (!th...@java.util.date::jsdate
+        || typeof th...@java.util.date::jsdate != "object") {
+      @java.util.Date::throwJsDateException(Ljava/lang/String;)(""
+          + th...@java.util.date::jsdate);
+    }
+  }-*/;
+
    private native double getTime0() /*-{
-    return this.jsdate.getTime();
+    th...@java.util.date::checkJsDate()();
+    return th...@java.util.date::jsdate.getTime();
    }-*/;

    private native void init() /*-{
-    this.jsdate = new Date();
+    th...@java.util.date::jsdate = new Date();
    }-*/;

    private native void init(double date) /*-{
-    this.jsdate = new Date(date);
+    th...@java.util.date::jsdate = new Date(date);
    }-*/;

    private native void init(int year, int month, int date, int hrs, int min,
        int sec) /*-{
-    this.jsdate = new Date();
-    this.jsdate.setFullYear(year + 1900, month, date);
-    this.jsdate.setHours(hrs, min, sec, 0);
+    th...@java.util.date::jsdate = new Date();
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setFullYear(year + 1900, month, date);
+    th...@java.util.date::jsdate.setHours(hrs, min, sec, 0);
    }-*/;

    private native void setTime0(double time) /*-{
-    this.jsdate.setTime(time);
+    th...@java.util.date::checkJsDate()();
+    th...@java.util.date::jsdate.setTime(time);
    }-*/;
  }

Modified: trunk/user/test/com/google/gwt/emultest/java/util/DateTest.java
==============================================================================
--- trunk/user/test/com/google/gwt/emultest/java/util/DateTest.java      
(original)
+++ trunk/user/test/com/google/gwt/emultest/java/util/DateTest.java     Mon  
Jun  1 22:59:06 2009
@@ -32,6 +32,21 @@
    public static final String PAST = "PAST";
    public static final long SECOND_MILLISECONDS_SHIFT = 10;

+  private static native void mungeDateNull(Date d) /*-{
+    d...@java.util.date::jsdate = null;
+  }-*/;
+
+  private static native void mungeDatePrimitive(Date d) /*-{
+    d...@java.util.date::jsdate = 42;
+  }-*/;
+
+  private static native void mungeDateUndef(Date d) /*-{
+    // use (void 0) to get an undefined value
+    d...@java.util.date::jsdate = (void 0);
+  }-*/;
+
+  Date theDate = new Date();
+
    /**
     * Sets module name so that javascript compiler can operate.
     */
@@ -94,6 +109,39 @@
      assertFalse(a2);
    }

+  /**
+   * Test that Date correctly catches when its internal jsdate
+   * instance is mangled.
+   */
+  public void testCheck() {
+    if (GWT.isScript()) {
+      Date d = new Date();
+      mungeDateNull(d);
+      try {
+        d.getHours();
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {
+        // do nothing
+      }
+      d = new Date();
+      mungeDateUndef(d);
+      try {
+        d.getHours();
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {
+        // do nothing
+      }
+      d = new Date();
+      mungeDatePrimitive(d);
+      try {
+        d.getHours();
+        fail("Expected IllegalStateException");
+      } catch (IllegalStateException expected) {
+        // do nothing
+      }
+    }
+  }
+
    /** Testing for public java.lang.Object java.util.Date.clone(). */
    public void testClone() {

@@ -303,6 +351,21 @@
      assertEquals(110, a2);
    }

+  /**
+   * Testing to that if we set the day number to 31 for a month that only  
has 30
+   * days in it, that the date rolls over to the first day of the next  
month in
+   * sequence.
+   */
+  public void testInvalidDateForMonth() {
+    int monthNum = 3; // April
+    int numDaysInOldMonth = 30;
+    int newDayNum = 31;
+    Date dateWithThirtyDays = new Date(2006, monthNum, 30);
+    dateWithThirtyDays.setDate(newDayNum);
+    assertEquals(dateWithThirtyDays.getMonth(), monthNum + 1);
+    assertEquals(dateWithThirtyDays.getDate(), newDayNum -  
numDaysInOldMonth);
+  }
+
    /** Testing for public static long  
java.util.Date.parse(java.lang.String). */
    public void testParse() {
      try {
@@ -356,21 +419,6 @@
      }
    }

-  /**
-   * Testing to that if we set the day number to 31 for a month that only  
has 30
-   * days in it, that the date rolls over to the first day of the next  
month in
-   * sequence.
-   */
-  public void testInvalidDateForMonth() {
-    int monthNum = 3; // April
-    int numDaysInOldMonth = 30;
-    int newDayNum = 31;
-    Date dateWithThirtyDays = new Date(2006, monthNum, 30);
-    dateWithThirtyDays.setDate(newDayNum);
-    assertEquals(dateWithThirtyDays.getMonth(), monthNum + 1);
-    assertEquals(dateWithThirtyDays.getDate(), newDayNum -  
numDaysInOldMonth);
-  }
-
    /** Testing for public void java.util.Date.setHours(int). */
    public void testSetHours() {
      for (int i = 0; i < 24; i++) {
@@ -380,6 +428,39 @@
      }
    }

+  /**
+   * We want to test to see that if we are currently in a month with 31  
days and
+   * we set the month to one which has less than 31 days, that the month
+   * returned by the date class will be one higher than the month that we
+   * originally set (according to the spec of java.util.date).
+   */
+  public void testSetInvalidMonthForDate() {
+    int dayNum = 31;
+    int newMonthNum = 1;
+    int numDaysInNewMonth = 28;
+    Date dateWithThirtyOneDays = new Date(2006, 12, dayNum);
+    dateWithThirtyOneDays.setMonth(newMonthNum);
+    assertEquals(dateWithThirtyOneDays.getMonth(), newMonthNum + 1);
+    assertEquals(dateWithThirtyOneDays.getDate(), dayNum -  
numDaysInNewMonth);
+  }
+
+  /**
+   * We want to test to see that if the date is Feb 29th (in a leap year)  
and we
+   * set the year to a non-leap year, that the month and day will roll  
over to
+   * March 1st.
+   */
+  public void testSetInvalidYearForDate() {
+    int dayNum = 29;
+    int monthNum = 1; // February
+    int newYearNum = 2005;
+    int numDaysInFebInNewYear = 28;
+    Date leapYearDate = new Date(2004, monthNum, dayNum);
+    leapYearDate.setYear(newYearNum);
+    assertEquals(leapYearDate.getYear(), newYearNum);
+    assertEquals(leapYearDate.getMonth(), monthNum + 1);
+    assertEquals(leapYearDate.getDate(), dayNum - numDaysInFebInNewYear);
+  }
+
    /** Testing for public void java.util.Date.setMinutes(int). */
    public void testSetMinutes() {
      for (int i = 0; i < 24; i++) {
@@ -403,22 +484,6 @@
      }
    }

-  /**
-   * We want to test to see that if we are currently in a month with 31  
days and
-   * we set the month to one which has less than 31 days, that the month
-   * returned by the date class will be one higher than the month that we
-   * originally set (according to the spec of java.util.date).
-   */
-  public void testSetInvalidMonthForDate() {
-    int dayNum = 31;
-    int newMonthNum = 1;
-    int numDaysInNewMonth = 28;
-    Date dateWithThirtyOneDays = new Date(2006, 12, dayNum);
-    dateWithThirtyOneDays.setMonth(newMonthNum);
-    assertEquals(dateWithThirtyOneDays.getMonth(), newMonthNum + 1);
-    assertEquals(dateWithThirtyOneDays.getDate(), dayNum -  
numDaysInNewMonth);
-  }
-
    /** Testing for public void java.util.Date.setSeconds(int). */
    public void testSetSeconds() {
      for (int i = 0; i < 24; i++) {
@@ -438,35 +503,6 @@
      }
    }

-  /** Testing for public void java.util.Date.setYear(int). */
-  public void testSetYear() {
-    for (int i = 1880; i < 2050; i++) {
-      // We want to use a fixed date here. If we use the current date, the
-      // assertion may fail
-      // when the date is February 29th, and we set the year to a non-leap  
year
-      Date accum0 = new Date(2006, 12, 01);
-      accum0.setYear(i);
-      assertEquals(accum0.getYear(), i);
-    }
-  }
-
-  /**
-   * We want to test to see that if the date is Feb 29th (in a leap year)  
and we
-   * set the year to a non-leap year, that the month and day will roll  
over to
-   * March 1st.
-   */
-  public void testSetInvalidYearForDate() {
-    int dayNum = 29;
-    int monthNum = 1; // February
-    int newYearNum = 2005;
-    int numDaysInFebInNewYear = 28;
-    Date leapYearDate = new Date(2004, monthNum, dayNum);
-    leapYearDate.setYear(newYearNum);
-    assertEquals(leapYearDate.getYear(), newYearNum);
-    assertEquals(leapYearDate.getMonth(), monthNum + 1);
-    assertEquals(leapYearDate.getDate(), dayNum - numDaysInFebInNewYear);
-  }
-
    /**
     * We want to test to see that if the date is Feb 29th (in a leap year)  
and we
     * set the year to another leap year, that the month and day will be  
retained.
@@ -483,6 +519,18 @@
      assertEquals(leapYearDate.getDate(), dayNum);
    }

+  /** Testing for public void java.util.Date.setYear(int). */
+  public void testSetYear() {
+    for (int i = 1880; i < 2050; i++) {
+      // We want to use a fixed date here. If we use the current date, the
+      // assertion may fail
+      // when the date is February 29th, and we set the year to a non-leap  
year
+      Date accum0 = new Date(2006, 12, 01);
+      accum0.setYear(i);
+      assertEquals(accum0.getYear(), i);
+    }
+  }
+
    /** Testing for public java.lang.String java.util.Date.toGMTString(). */
    public void testToGMTString() {

@@ -618,6 +666,4 @@
    private long roundToDay(long accum0) {
      return accum0 >> DAY_MILLISECONDS_SHIFT << DAY_MILLISECONDS_SHIFT;
    }
-
-  Date theDate = new Date();
  }

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to