Reviewers: jgw,

Description:
Description:
===========
If an event fires while a preview handler is handling an event, the
NativePreviewEvent singleton will be reset but not returned to its
original state. I observed this behavior occurring natively on Chrome
and Safari, but it can also occur programatically.

Fix:
====
We now store the current state of the NativePreviewEvent before
resetting it, and return it to its original state before exiting the
fire method.

Testing:
=======
I added a JUnit test and confirmed that it fails without the fix, but
passes with it.

Please review this at http://gwt-code-reviews.appspot.com/68804

Affected files:
   user/src/com/google/gwt/user/client/Event.java
   user/test/com/google/gwt/user/client/EventTest.java


Index: user/src/com/google/gwt/user/client/Event.java
===================================================================
--- user/src/com/google/gwt/user/client/Event.java      (revision 6161)
+++ user/src/com/google/gwt/user/client/Event.java      (working copy)
@@ -72,13 +72,27 @@
       */
      private static boolean fire(HandlerManager handlers, NativeEvent  
nativeEvent) {
        if (TYPE != null && handlers != null &&  
handlers.isEventHandled(TYPE)) {
+        // Cache the current values in the singleton in case we are in the
+        // middle of handling another event.
+        boolean lastIsCanceled = singleton.isCanceled;
+        boolean lastIsConsumed = singleton.isConsumed;
+        boolean lastIsFirstHandler = singleton.isFirstHandler;
+        NativeEvent lastNativeEvent = singleton.nativeEvent;
+
          // Revive the event
          singleton.revive();
          singleton.setNativeEvent(nativeEvent);

          // Fire the event
          handlers.fireEvent(singleton);
-        return !(singleton.isCanceled() && !singleton.isConsumed());
+        boolean ret = !(singleton.isCanceled() && !singleton.isConsumed());
+
+        // Restore the state of the singleton.
+        singleton.isCanceled = lastIsCanceled;
+        singleton.isConsumed = lastIsConsumed;
+        singleton.isFirstHandler = lastIsFirstHandler;
+        singleton.nativeEvent = lastNativeEvent;
+        return ret;
        }
        return true;
      }
Index: user/test/com/google/gwt/user/client/EventTest.java
===================================================================
--- user/test/com/google/gwt/user/client/EventTest.java (revision 6161)
+++ user/test/com/google/gwt/user/client/EventTest.java (working copy)
@@ -326,6 +326,29 @@

    /**
     * Test that {...@link Event#fireNativePreviewEvent(NativeEvent)} returns  
the
+   * correct value even if another event is fired while handling the  
current
+   * event.
+   */
+  public void testFireNativePreviewEventWithInterupt() {
+    NativePreviewHandler handler = new NativePreviewHandler() {
+      private boolean first = true;
+
+      public void onPreviewNativeEvent(NativePreviewEvent event) {
+        if (first) {
+          event.cancel();
+          first = false;
+          assertTrue(Event.fireNativePreviewEvent(null));
+          assertTrue(event.isCanceled());
+        }
+      }
+    };
+    HandlerRegistration reg = Event.addNativePreviewHandler(handler);
+    assertFalse(Event.fireNativePreviewEvent(null));
+    reg.removeHandler();
+  }
+
+  /**
+   * Test that {...@link Event#fireNativePreviewEvent(NativeEvent)} returns  
the
     * correct value if the native event is not canceled.
     */
    public void testFireNativePreviewEventWithoutCancel() {
@@ -524,6 +547,6 @@
    }

    private native boolean isInternetExplorer() /*-{
-     return navigator.userAgent.toLowerCase().indexOf("msie") != -1;
-   }-*/;
+    return navigator.userAgent.toLowerCase().indexOf("msie") != -1;
+  }-*/;
  }



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

Reply via email to