]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix client-side memory leak caused by Grid events (#9103)
authorAleksi Hietanen <aleksi@vaadin.com>
Wed, 19 Apr 2017 10:54:16 +0000 (13:54 +0300)
committerTeemu Suo-Anttila <tsuoanttila@users.noreply.github.com>
Mon, 8 May 2017 11:46:35 +0000 (14:46 +0300)
Refactors AbstractGridKeyEvent, AbstractGridMouseEvent and their
descendants to follow the pattern used in other GWT DomEvents.

Fixes #7633

13 files changed:
client/src/main/java/com/vaadin/client/widget/grid/events/GridClickEvent.java
client/src/main/java/com/vaadin/client/widget/grid/events/GridDoubleClickEvent.java
client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyDownEvent.java
client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyPressEvent.java
client/src/main/java/com/vaadin/client/widget/grid/events/GridKeyUpEvent.java
client/src/main/java/com/vaadin/client/widgets/Grid.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridClickEvent.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridDoubleClickEvent.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyDownEvent.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyPressEvent.java
compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/events/GridKeyUpEvent.java
compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java
uitest/src/main/java/com/vaadin/tests/components/grid/GridClientMemoryLeak.java [new file with mode: 0644]

index 6bcfab2375e043af7d2d43fc5ee14e1da600140a..788a06a068e481dc32f7c415cadf0cec6fffe054 100644 (file)
@@ -30,8 +30,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
  */
 public class GridClickEvent extends AbstractGridMouseEvent<GridClickHandler> {
 
+    public static final Type<GridClickHandler> TYPE = new Type<GridClickHandler>(
+            BrowserEvents.CLICK, new GridClickEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridClickEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridClickEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridClickHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
index 7b0c00f6fffaf428c9494b725cf6b0ca09b091ec..6f4653d9ba241b04c9bed7dc94f9ccf97eacdaf9 100644 (file)
@@ -31,8 +31,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
 public class GridDoubleClickEvent
         extends AbstractGridMouseEvent<GridDoubleClickHandler> {
 
+    public static final Type<GridDoubleClickHandler> TYPE = new Type<GridDoubleClickHandler>(
+            BrowserEvents.DBLCLICK, new GridDoubleClickEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridDoubleClickEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridDoubleClickEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridDoubleClickHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
@@ -51,5 +69,4 @@ public class GridDoubleClickEvent
             handler.onDoubleClick(this);
         }
     }
-
 }
index 6f712ec05de5967b8072e1ad729da02e515ab266..aebd2155bead7ebab66bbff298b7c1f960176352 100644 (file)
@@ -31,8 +31,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
  */
 public class GridKeyDownEvent extends AbstractGridKeyEvent<GridKeyDownHandler> {
 
+    public static final Type<GridKeyDownHandler> TYPE = new Type<GridKeyDownHandler>(
+            BrowserEvents.KEYDOWN, new GridKeyDownEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridKeyDownEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridKeyDownEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridKeyDownHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
index 9f0bc8ab5d5d4ebdb469f2efec0afd87c899d082..a0d93a870d8d01b1fc66b32de428219d98ecaf30 100644 (file)
@@ -31,8 +31,26 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
 public class GridKeyPressEvent
         extends AbstractGridKeyEvent<GridKeyPressHandler> {
 
+    public static final Type<GridKeyPressHandler> TYPE = new Type<GridKeyPressHandler>(
+            BrowserEvents.KEYPRESS, new GridKeyPressEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridKeyPressEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridKeyPressEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridKeyPressHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
index 0cc7fc1fb7bc5fa0c53a1921438fab760f8249b9..1d029d1847d65f710577dbd49a51e8331d399240 100644 (file)
@@ -31,8 +31,21 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
  */
 public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {
 
+    public static final Type<GridKeyUpHandler> TYPE = new Type<GridKeyUpHandler>(
+            BrowserEvents.KEYUP, new GridKeyUpEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridKeyUpEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridKeyUpEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
     }
 
     @Override
@@ -46,6 +59,11 @@ public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {
         }
     }
 
+    @Override
+    public Type<GridKeyUpHandler> getAssociatedType() {
+        return TYPE;
+    }
+
     @Override
     protected String getBrowserEventType() {
         return BrowserEvents.KEYUP;
index eb5e38773b6a10ca33a0d738197dda3cf9ac7bfb..16ae0f2540247f6bd442ede8b40da9a85fd1b5f1 100755 (executable)
@@ -2291,47 +2291,59 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     public static abstract class AbstractGridKeyEvent<HANDLER extends AbstractGridKeyEventHandler>
             extends KeyEvent<HANDLER> {
 
-        private Grid<?> grid;
-        private final Type<HANDLER> associatedType = new Type<>(
-                getBrowserEventType(), this);
-        private final CellReference<?> targetCell;
+        /**
+         * @since 7.7.9
+         */
+        public AbstractGridKeyEvent() {
+        }
 
+        /**
+         * @deprecated This constructor's arguments are no longer used. Use the
+         *             no-args constructor instead.
+         */
+        @Deprecated
         public AbstractGridKeyEvent(Grid<?> grid, CellReference<?> targetCell) {
-            this.grid = grid;
-            this.targetCell = targetCell;
         }
 
         protected abstract String getBrowserEventType();
 
         /**
-         * Gets the Grid instance for this event.
+         * Gets the Grid instance for this event, if it originated from a Grid.
          *
-         * @return grid
+         * @return the grid this event originated from, or {@code null} if this
+         *         event did not originate from a grid
          */
         public Grid<?> getGrid() {
-            return grid;
+            EventTarget target = getNativeEvent().getEventTarget();
+            if (!Element.is(target)) {
+                return null;
+            }
+            return WidgetUtil.findWidget(Element.as(target), Grid.class);
         }
 
         /**
-         * Gets the focused cell for this event.
+         * Gets the reference of target cell for this event, if this event
+         * originated from a Grid.
          *
-         * @return focused cell
+         * @return target cell, or {@code null} if this event did not originate
+         *         from a grid
          */
         public CellReference<?> getFocusedCell() {
-            return targetCell;
+            return getGrid().getEventCell();
         }
 
         @Override
         protected void dispatch(HANDLER handler) {
             EventTarget target = getNativeEvent().getEventTarget();
-            if (Element.is(target)
+            Grid<?> grid = getGrid();
+            if (Element.is(target) && grid != null
                     && !grid.isElementInChildWidget(Element.as(target))) {
 
                 Section section = Section.FOOTER;
                 final RowContainer container = grid.cellFocusHandler.containerWithFocus;
                 if (container == grid.escalator.getHeader()) {
                     section = Section.HEADER;
-                } else if (container == grid.escalator.getBody()) {
+                } else if (container == getGrid().escalator.getBody()) {
                     section = Section.BODY;
                 }
 
@@ -2340,45 +2352,55 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         }
 
         protected abstract void doDispatch(HANDLER handler, Section section);
-
-        @Override
-        public Type<HANDLER> getAssociatedType() {
-            return associatedType;
-        }
     }
 
     public static abstract class AbstractGridMouseEvent<HANDLER extends AbstractGridMouseEventHandler>
             extends MouseEvent<HANDLER> {
 
-        private Grid<?> grid;
-        private final CellReference<?> targetCell;
-        private final Type<HANDLER> associatedType = new Type<>(
-                getBrowserEventType(), this);
+        /**
+         * @since 7.7.9
+         */
+        public AbstractGridMouseEvent() {
+        }
 
+        /**
+         * @deprecated This constructor's arguments are no longer used. Use the
+         *             no-args constructor instead.
+         */
+        @Deprecated
         public AbstractGridMouseEvent(Grid<?> grid,
                 CellReference<?> targetCell) {
-            this.grid = grid;
-            this.targetCell = targetCell;
         }
 
         protected abstract String getBrowserEventType();
 
         /**
-         * Gets the Grid instance for this event.
+         * Gets the Grid instance for this event, if it originated from a Grid.
          *
-         * @return grid
+         * @return the grid this event originated from, or {@code null} if this
+         *         event did not originate from a grid
          */
         public Grid<?> getGrid() {
-            return grid;
+            EventTarget target = getNativeEvent().getEventTarget();
+            if (!Element.is(target)) {
+                return null;
+            }
+            return WidgetUtil.findWidget(Element.as(target), Grid.class);
         }
 
         /**
-         * Gets the reference of target cell for this event.
+         * Gets the reference of target cell for this event, if this event
+         * originated from a Grid.
          *
-         * @return target cell
+         * @return target cell, or {@code null} if this event did not originate
+         *         from a grid
          */
         public CellReference<?> getTargetCell() {
-            return targetCell;
+            Grid<?> grid = getGrid();
+            if (grid == null) {
+                return null;
+            }
+            return grid.getEventCell();
         }
 
         @Override
@@ -2389,6 +2411,12 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                 return;
             }
 
+            Grid<?> grid = getGrid();
+            if (grid == null) {
+                // Target is not an element of a grid
+                return;
+            }
+
             Element targetElement = Element.as(target);
             if (grid.isElementInChildWidget(targetElement)) {
                 // Target is some widget inside of Grid
@@ -2413,11 +2441,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         }
 
         protected abstract void doDispatch(HANDLER handler, Section section);
-
-        @Override
-        public Type<HANDLER> getAssociatedType() {
-            return associatedType;
-        }
     }
 
     private static final String CUSTOM_STYLE_PROPERTY_NAME = "customStyle";
@@ -2430,13 +2453,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     private static final double DETAILS_ROW_INITIAL_HEIGHT = 50;
 
-    private EventCellReference<T> eventCell = new EventCellReference<>(this);
-    private GridKeyDownEvent keyDown = new GridKeyDownEvent(this, eventCell);
-    private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell);
-    private GridKeyPressEvent keyPress = new GridKeyPressEvent(this, eventCell);
-    private GridClickEvent clickEvent = new GridClickEvent(this, eventCell);
-    private GridDoubleClickEvent doubleClickEvent = new GridDoubleClickEvent(
-            this, eventCell);
+    private EventCellReference<T> eventCell = new EventCellReference<T>(this);
 
     private class CellFocusHandler {
 
@@ -8090,7 +8107,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addBodyKeyDownHandler(
             BodyKeyDownHandler handler) {
-        return addHandler(handler, keyDown.getAssociatedType());
+        return addHandler(handler, GridKeyDownEvent.TYPE);
     }
 
     /**
@@ -8103,7 +8120,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return the registration for the event
      */
     public HandlerRegistration addBodyKeyUpHandler(BodyKeyUpHandler handler) {
-        return addHandler(handler, keyUp.getAssociatedType());
+        return addHandler(handler, GridKeyUpEvent.TYPE);
     }
 
     /**
@@ -8117,7 +8134,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addBodyKeyPressHandler(
             BodyKeyPressHandler handler) {
-        return addHandler(handler, keyPress.getAssociatedType());
+        return addHandler(handler, GridKeyPressEvent.TYPE);
     }
 
     /**
@@ -8131,7 +8148,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderKeyDownHandler(
             HeaderKeyDownHandler handler) {
-        return addHandler(handler, keyDown.getAssociatedType());
+        return addHandler(handler, GridKeyDownEvent.TYPE);
     }
 
     /**
@@ -8145,7 +8162,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderKeyUpHandler(
             HeaderKeyUpHandler handler) {
-        return addHandler(handler, keyUp.getAssociatedType());
+        return addHandler(handler, GridKeyUpEvent.TYPE);
     }
 
     /**
@@ -8159,7 +8176,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderKeyPressHandler(
             HeaderKeyPressHandler handler) {
-        return addHandler(handler, keyPress.getAssociatedType());
+        return addHandler(handler, GridKeyPressEvent.TYPE);
     }
 
     /**
@@ -8173,7 +8190,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterKeyDownHandler(
             FooterKeyDownHandler handler) {
-        return addHandler(handler, keyDown.getAssociatedType());
+        return addHandler(handler, GridKeyDownEvent.TYPE);
     }
 
     /**
@@ -8187,7 +8204,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterKeyUpHandler(
             FooterKeyUpHandler handler) {
-        return addHandler(handler, keyUp.getAssociatedType());
+        return addHandler(handler, GridKeyUpEvent.TYPE);
     }
 
     /**
@@ -8201,7 +8218,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterKeyPressHandler(
             FooterKeyPressHandler handler) {
-        return addHandler(handler, keyPress.getAssociatedType());
+        return addHandler(handler, GridKeyPressEvent.TYPE);
     }
 
     /**
@@ -8213,7 +8230,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return the registration for the event
      */
     public HandlerRegistration addBodyClickHandler(BodyClickHandler handler) {
-        return addHandler(handler, clickEvent.getAssociatedType());
+        return addHandler(handler, GridClickEvent.TYPE);
     }
 
     /**
@@ -8226,7 +8243,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderClickHandler(
             HeaderClickHandler handler) {
-        return addHandler(handler, clickEvent.getAssociatedType());
+        return addHandler(handler, GridClickEvent.TYPE);
     }
 
     /**
@@ -8239,7 +8256,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterClickHandler(
             FooterClickHandler handler) {
-        return addHandler(handler, clickEvent.getAssociatedType());
+        return addHandler(handler, GridClickEvent.TYPE);
     }
 
     /**
@@ -8253,7 +8270,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addBodyDoubleClickHandler(
             BodyDoubleClickHandler handler) {
-        return addHandler(handler, doubleClickEvent.getAssociatedType());
+        return addHandler(handler, GridDoubleClickEvent.TYPE);
     }
 
     /**
@@ -8267,7 +8284,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderDoubleClickHandler(
             HeaderDoubleClickHandler handler) {
-        return addHandler(handler, doubleClickEvent.getAssociatedType());
+        return addHandler(handler, GridDoubleClickEvent.TYPE);
     }
 
     /**
@@ -8281,7 +8298,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterDoubleClickHandler(
             FooterDoubleClickHandler handler) {
-        return addHandler(handler, doubleClickEvent.getAssociatedType());
+        return addHandler(handler, GridDoubleClickEvent.TYPE);
     }
 
     /**
@@ -8758,7 +8775,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         for (int row : details) {
             setDetailsVisible(row, false);
         }
-
         super.onDetach();
     }
 
index 8f2350727fa6702c3222efd272b933558a672778..ec1559b9da5a4b9437beffe2652e554e04257fd9 100644 (file)
@@ -30,8 +30,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
  */
 public class GridClickEvent extends AbstractGridMouseEvent<GridClickHandler> {
 
+    public static final Type<GridClickHandler> TYPE = new Type<GridClickHandler>(
+            BrowserEvents.CLICK, new GridClickEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridClickEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridClickEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridClickHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
index 711e70f3b4fda0d94791288b074a8c3605aff5e8..17231ee3a8a31637579cefe84196d60e32187236 100644 (file)
@@ -31,8 +31,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
 public class GridDoubleClickEvent
         extends AbstractGridMouseEvent<GridDoubleClickHandler> {
 
+    public static final Type<GridDoubleClickHandler> TYPE = new Type<GridDoubleClickHandler>(
+            BrowserEvents.DBLCLICK, new GridDoubleClickEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridDoubleClickEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridDoubleClickEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridDoubleClickHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
@@ -51,5 +69,4 @@ public class GridDoubleClickEvent
             handler.onDoubleClick(this);
         }
     }
-
 }
index e4405b69a57f5b671eed6685ef93647f350eadea..617798cb3c20733e0a8d39bd7e323e928c1320e1 100644 (file)
@@ -31,8 +31,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
  */
 public class GridKeyDownEvent extends AbstractGridKeyEvent<GridKeyDownHandler> {
 
+    public static final Type<GridKeyDownHandler> TYPE = new Type<GridKeyDownHandler>(
+            BrowserEvents.KEYDOWN, new GridKeyDownEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridKeyDownEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridKeyDownEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridKeyDownHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
index 86a4664df03a678c141fd9930cc03af64c41d141..1ada27a1f68d3562a91376816d5f1bc597cfdba2 100644 (file)
@@ -31,8 +31,26 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
 public class GridKeyPressEvent
         extends AbstractGridKeyEvent<GridKeyPressHandler> {
 
+    public static final Type<GridKeyPressHandler> TYPE = new Type<GridKeyPressHandler>(
+            BrowserEvents.KEYPRESS, new GridKeyPressEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridKeyPressEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridKeyPressEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
+    }
+
+    @Override
+    public Type<GridKeyPressHandler> getAssociatedType() {
+        return TYPE;
     }
 
     @Override
index 770f0214f9974673d52f7dee1a0ddfc1a3d18799..ec81e65ea836d05279e3ac38bc6d6b10bc273ee5 100644 (file)
@@ -31,8 +31,21 @@ import com.vaadin.v7.shared.ui.grid.GridConstants.Section;
  */
 public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {
 
+    public static final Type<GridKeyUpHandler> TYPE = new Type<GridKeyUpHandler>(
+            BrowserEvents.KEYUP, new GridKeyUpEvent());
+
+    /**
+     * @since 7.7.9
+     */
+    public GridKeyUpEvent() {
+    }
+
+    /**
+     * @deprecated This constructor's arguments are no longer used. Use the
+     *             no-args constructor instead.
+     */
+    @Deprecated
     public GridKeyUpEvent(Grid<?> grid, CellReference<?> targetCell) {
-        super(grid, targetCell);
     }
 
     @Override
@@ -46,6 +59,11 @@ public class GridKeyUpEvent extends AbstractGridKeyEvent<GridKeyUpHandler> {
         }
     }
 
+    @Override
+    public Type<GridKeyUpHandler> getAssociatedType() {
+        return TYPE;
+    }
+
     @Override
     protected String getBrowserEventType() {
         return BrowserEvents.KEYUP;
index 7ba5c9cc8271dd8422344cc0b6c865090a13f367..3efb253e3a71311cf0b67dbfa00de10b49415435 100644 (file)
@@ -2298,94 +2298,115 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     public static abstract class AbstractGridKeyEvent<HANDLER extends AbstractGridKeyEventHandler>
             extends KeyEvent<HANDLER> {
 
-        private Grid<?> grid;
-        private final Type<HANDLER> associatedType = new Type<HANDLER>(
-                getBrowserEventType(), this);
-        private final CellReference<?> targetCell;
+        /**
+         * @since 7.7.9
+         */
+        public AbstractGridKeyEvent() {
+        }
 
+        /**
+         * @deprecated This constructor's arguments are no longer used. Use the
+         *             no-args constructor instead.
+         */
+        @Deprecated
         public AbstractGridKeyEvent(Grid<?> grid, CellReference<?> targetCell) {
-            this.grid = grid;
-            this.targetCell = targetCell;
         }
 
         protected abstract String getBrowserEventType();
 
         /**
-         * Gets the Grid instance for this event.
+         * Gets the Grid instance for this event, if it originated from a Grid.
          *
-         * @return grid
+         * @return the grid this event originated from, or {@code null} if this
+         *         event did not originate from a grid
          */
         public Grid<?> getGrid() {
-            return grid;
+            EventTarget target = getNativeEvent().getEventTarget();
+            if (!Element.is(target)) {
+                return null;
+            }
+            return WidgetUtil.findWidget(Element.as(target), Grid.class);
         }
 
         /**
-         * Gets the focused cell for this event.
+         * Gets the reference of target cell for this event, if this event
+         * originated from a Grid.
          *
-         * @return focused cell
+         * @return target cell, or {@code null} if this event did not originate
+         *         from a grid
          */
         public CellReference<?> getFocusedCell() {
-            return targetCell;
+            return getGrid().getEventCell();
         }
 
         @Override
         protected void dispatch(HANDLER handler) {
             EventTarget target = getNativeEvent().getEventTarget();
-            if (Element.is(target)
+            Grid<?> grid = getGrid();
+            if (Element.is(target) && grid != null
                     && !grid.isElementInChildWidget(Element.as(target))) {
 
                 Section section = Section.FOOTER;
                 final RowContainer container = grid.cellFocusHandler.containerWithFocus;
                 if (container == grid.escalator.getHeader()) {
                     section = Section.HEADER;
-                } else if (container == grid.escalator.getBody()) {
+                } else if (container == getGrid().escalator.getBody()) {
                     section = Section.BODY;
                 }
-
                 doDispatch(handler, section);
             }
         }
 
         protected abstract void doDispatch(HANDLER handler, Section section);
-
-        @Override
-        public Type<HANDLER> getAssociatedType() {
-            return associatedType;
-        }
     }
 
     public static abstract class AbstractGridMouseEvent<HANDLER extends AbstractGridMouseEventHandler>
             extends MouseEvent<HANDLER> {
 
-        private Grid<?> grid;
-        private final CellReference<?> targetCell;
-        private final Type<HANDLER> associatedType = new Type<HANDLER>(
-                getBrowserEventType(), this);
+        /**
+         * @since 7.7.9
+         */
+        public AbstractGridMouseEvent() {
+        }
 
+        /**
+         * @deprecated This constructor's arguments are no longer used. Use the
+         *             no-args constructor instead.
+         */
+        @Deprecated
         public AbstractGridMouseEvent(Grid<?> grid,
                 CellReference<?> targetCell) {
-            this.grid = grid;
-            this.targetCell = targetCell;
         }
 
         protected abstract String getBrowserEventType();
 
         /**
-         * Gets the Grid instance for this event.
+         * Gets the Grid instance for this event, if it originated from a Grid.
          *
-         * @return grid
+         * @return the grid this event originated from, or {@code null} if this
+         *         event did not originate from a grid
          */
         public Grid<?> getGrid() {
-            return grid;
+            EventTarget target = getNativeEvent().getEventTarget();
+            if (!Element.is(target)) {
+                return null;
+            }
+            return WidgetUtil.findWidget(Element.as(target), Grid.class);
         }
 
         /**
-         * Gets the reference of target cell for this event.
+         * Gets the reference of target cell for this event, if this event
+         * originated from a Grid.
          *
-         * @return target cell
+         * @return target cell, or {@code null} if this event did not originate
+         *         from a grid
          */
         public CellReference<?> getTargetCell() {
-            return targetCell;
+            Grid<?> grid = getGrid();
+            if (grid == null) {
+                return null;
+            }
+            return grid.getEventCell();
         }
 
         @Override
@@ -2396,6 +2417,12 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
                 return;
             }
 
+            Grid<?> grid = getGrid();
+            if (grid == null) {
+                // Target is not an element of a grid
+                return;
+            }
+
             Element targetElement = Element.as(target);
             if (grid.isElementInChildWidget(targetElement)) {
                 // Target is some widget inside of Grid
@@ -2420,11 +2447,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
         }
 
         protected abstract void doDispatch(HANDLER handler, Section section);
-
-        @Override
-        public Type<HANDLER> getAssociatedType() {
-            return associatedType;
-        }
     }
 
     private static final String CUSTOM_STYLE_PROPERTY_NAME = "customStyle";
@@ -2438,12 +2460,6 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
     private static final double DETAILS_ROW_INITIAL_HEIGHT = 50;
 
     private EventCellReference<T> eventCell = new EventCellReference<T>(this);
-    private GridKeyDownEvent keyDown = new GridKeyDownEvent(this, eventCell);
-    private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell);
-    private GridKeyPressEvent keyPress = new GridKeyPressEvent(this, eventCell);
-    private GridClickEvent clickEvent = new GridClickEvent(this, eventCell);
-    private GridDoubleClickEvent doubleClickEvent = new GridDoubleClickEvent(
-            this, eventCell);
 
     private class CellFocusHandler {
 
@@ -8176,7 +8192,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addBodyKeyDownHandler(
             BodyKeyDownHandler handler) {
-        return addHandler(handler, keyDown.getAssociatedType());
+        return addHandler(handler, GridKeyDownEvent.TYPE);
     }
 
     /**
@@ -8189,7 +8205,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return the registration for the event
      */
     public HandlerRegistration addBodyKeyUpHandler(BodyKeyUpHandler handler) {
-        return addHandler(handler, keyUp.getAssociatedType());
+        return addHandler(handler, GridKeyUpEvent.TYPE);
     }
 
     /**
@@ -8203,7 +8219,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addBodyKeyPressHandler(
             BodyKeyPressHandler handler) {
-        return addHandler(handler, keyPress.getAssociatedType());
+        return addHandler(handler, GridKeyPressEvent.TYPE);
     }
 
     /**
@@ -8217,7 +8233,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderKeyDownHandler(
             HeaderKeyDownHandler handler) {
-        return addHandler(handler, keyDown.getAssociatedType());
+        return addHandler(handler, GridKeyDownEvent.TYPE);
     }
 
     /**
@@ -8231,7 +8247,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderKeyUpHandler(
             HeaderKeyUpHandler handler) {
-        return addHandler(handler, keyUp.getAssociatedType());
+        return addHandler(handler, GridKeyUpEvent.TYPE);
     }
 
     /**
@@ -8245,7 +8261,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderKeyPressHandler(
             HeaderKeyPressHandler handler) {
-        return addHandler(handler, keyPress.getAssociatedType());
+        return addHandler(handler, GridKeyPressEvent.TYPE);
     }
 
     /**
@@ -8259,7 +8275,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterKeyDownHandler(
             FooterKeyDownHandler handler) {
-        return addHandler(handler, keyDown.getAssociatedType());
+        return addHandler(handler, GridKeyDownEvent.TYPE);
     }
 
     /**
@@ -8273,7 +8289,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterKeyUpHandler(
             FooterKeyUpHandler handler) {
-        return addHandler(handler, keyUp.getAssociatedType());
+        return addHandler(handler, GridKeyUpEvent.TYPE);
     }
 
     /**
@@ -8287,7 +8303,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterKeyPressHandler(
             FooterKeyPressHandler handler) {
-        return addHandler(handler, keyPress.getAssociatedType());
+        return addHandler(handler, GridKeyPressEvent.TYPE);
     }
 
     /**
@@ -8299,7 +8315,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      * @return the registration for the event
      */
     public HandlerRegistration addBodyClickHandler(BodyClickHandler handler) {
-        return addHandler(handler, clickEvent.getAssociatedType());
+        return addHandler(handler, GridClickEvent.TYPE);
     }
 
     /**
@@ -8312,7 +8328,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderClickHandler(
             HeaderClickHandler handler) {
-        return addHandler(handler, clickEvent.getAssociatedType());
+        return addHandler(handler, GridClickEvent.TYPE);
     }
 
     /**
@@ -8325,7 +8341,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterClickHandler(
             FooterClickHandler handler) {
-        return addHandler(handler, clickEvent.getAssociatedType());
+        return addHandler(handler, GridClickEvent.TYPE);
     }
 
     /**
@@ -8339,7 +8355,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addBodyDoubleClickHandler(
             BodyDoubleClickHandler handler) {
-        return addHandler(handler, doubleClickEvent.getAssociatedType());
+        return addHandler(handler, GridDoubleClickEvent.TYPE);
     }
 
     /**
@@ -8353,7 +8369,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addHeaderDoubleClickHandler(
             HeaderDoubleClickHandler handler) {
-        return addHandler(handler, doubleClickEvent.getAssociatedType());
+        return addHandler(handler, GridDoubleClickEvent.TYPE);
     }
 
     /**
@@ -8367,7 +8383,7 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
      */
     public HandlerRegistration addFooterDoubleClickHandler(
             FooterDoubleClickHandler handler) {
-        return addHandler(handler, doubleClickEvent.getAssociatedType());
+        return addHandler(handler, GridDoubleClickEvent.TYPE);
     }
 
     /**
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridClientMemoryLeak.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridClientMemoryLeak.java
new file mode 100644 (file)
index 0000000..7071f18
--- /dev/null
@@ -0,0 +1,40 @@
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.ContentMode;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.VerticalLayout;
+
+public class GridClientMemoryLeak extends AbstractTestUI {
+
+    private static final String INSTRUCTIONS = "This UI is for manually testing that the client side grid does not leak memory. "
+            + "Steps to take:\n"
+            + "\t1. Click the newGrid button 1-n times\n"
+            + "\t2. Capture a JS heap dump in your browser\n"
+            + "\t3. The heap dump should only contain 1 instance of each of the following:\n"
+            + "\t\tGrid, GridKeyDownEvent, GridKeyPressEvent, GridKeyUpEvent, GridClickEvent, GridDoubleClickEvent";
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        final Label instructionLabel = new Label(INSTRUCTIONS,
+                ContentMode.PREFORMATTED);
+        final VerticalLayout layout = new VerticalLayout();
+        final Button btn = new Button("newGrid");
+        btn.addClickListener(new Button.ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                layout.removeComponent(layout.getComponent(1));
+                layout.addComponent(new Grid<String>());
+            }
+        });
+        layout.addComponent(instructionLabel);
+        layout.addComponent(btn);
+        layout.addComponent(new Grid<String>());
+        addComponent(layout);
+    }
+}