Fixes a memory leak in ScrollImplTrident by removing references from elements to GWT code.
http://gwt-code-reviews.appspot.com/1601803/
Issue: 7015
Author: stephen.haberman, dirk.scheffler
Review: jlabanca
Review by: rdayal@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10823 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/ScrollImpl.java b/user/src/com/google/gwt/user/client/ui/ScrollImpl.java
index 06e8a20..93cc023 100644
--- a/user/src/com/google/gwt/user/client/ui/ScrollImpl.java
+++ b/user/src/com/google/gwt/user/client/ui/ScrollImpl.java
@@ -16,6 +16,7 @@
package com.google.gwt.user.client.ui;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
@@ -31,38 +32,64 @@
*/
static class ScrollImplTrident extends ScrollImpl {
+ private static JavaScriptObject scrollHandler;
+
+ private static JavaScriptObject resizeHandler;
+
+ /**
+ * Creates static, leak-safe scroll/resize handlers.
+ */
+ private static native void initStaticHandlers() /*-{
+ // caches last scroll position
+ @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::scrollHandler = function() {
+ var scrollableElem = $wnd.event.srcElement;
+ scrollableElem.__lastScrollTop = scrollableElem.scrollTop;
+ scrollableElem.__lastScrollLeft = scrollableElem.scrollLeft;
+ };
+ // watches for resizes that should fire a fake scroll event
+ @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::resizeHandler = function() {
+ var scrollableElem = $wnd.event.srcElement;
+ if (scrollableElem.__isScrollContainer) {
+ scrollableElem = scrollableElem.parentNode;
+ }
+ // Give the browser a chance to fire a native scroll event before synthesizing one.
+ setTimeout($entry(function() {
+ // Trigger a synthetic scroll event if the scroll position changes.
+ if (scrollableElem.scrollTop != scrollableElem.__lastScrollTop ||
+ scrollableElem.scrollLeft != scrollableElem.__lastScrollLeft) {
+ // Update scroll positions.
+ scrollableElem.__lastScrollTop = scrollableElem.scrollTop;
+ scrollableElem.__lastScrollLeft = scrollableElem.scrollLeft;
+ @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::triggerScrollEvent(Lcom/google/gwt/dom/client/Element;)
+ (scrollableElem);
+ }
+ }), 1);
+ };
+ }-*/;
+
private static void triggerScrollEvent(Element elem) {
elem.dispatchEvent(Document.get().createScrollEvent());
}
+ ScrollImplTrident() {
+ initStaticHandlers();
+ }
+
@Override
public native void initialize(Element scrollable, Element container) /*-{
// Remember the last scroll position.
- var scrollableElem = scrollable;
- scrollableElem.__lastScrollTop = scrollableElem.__lastScrollLeft = 0;
- var scrollHandler = $entry(function() {
- scrollableElem.__lastScrollTop = scrollableElem.scrollTop;
- scrollableElem.__lastScrollLeft = scrollableElem.scrollLeft;
- });
- scrollable.attachEvent('onscroll', scrollHandler);
+ scrollable.__lastScrollTop = scrollable.__lastScrollLeft = 0;
+ scrollable.attachEvent('onscroll',
+ @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::scrollHandler);
// Detect if the scrollable element or the container within it changes
// size, either of which could affect the scroll position.
- var resizeHandler = $entry(function() {
- // Give the browser a chance to fire a native scroll event before
- // synthesizing one.
- setTimeout($entry(function() {
- // Trigger a synthetic scroll event if the scroll position changes.
- if (scrollableElem.scrollTop != scrollableElem.__lastScrollTop ||
- scrollableElem.scrollLeft != scrollableElem.__lastScrollLeft) {
- scrollHandler(); // Update scroll positions.
- @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::triggerScrollEvent(Lcom/google/gwt/dom/client/Element;)
- (scrollableElem);
- }
- }), 1);
- });
- scrollable.attachEvent('onresize', resizeHandler);
- container.attachEvent('onresize', resizeHandler);
+ scrollable.attachEvent('onresize',
+ @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::resizeHandler);
+ container.attachEvent('onresize',
+ @com.google.gwt.user.client.ui.ScrollImpl.ScrollImplTrident::resizeHandler);
+ // use boolean (primitive, won't leak) hint to resizeHandler that its the container
+ container.__isScrollContainer = true;
}-*/;
@Override