Integrate r11111 into releases/2.5.

Review by: jlabanca@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.5@11118 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE9.java b/user/src/com/google/gwt/dom/client/DOMImplIE9.java
index 1ccac0f..6564bb2 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE9.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE9.java
@@ -68,6 +68,12 @@
   }-*/;
 
   @Override
+  public boolean isOrHasChild(Node parent, Node child) {
+    // IE9 still behaves like IE6-8 for this method
+    return DOMImplTrident.isOrHasChildImpl(parent, child);
+  }
+
+  @Override
   public native void selectRemoveOption(SelectElement select, int index) /*-{
     try {
       // IE9 throws if elem at index is an optgroup
diff --git a/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java b/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
index 68aafb6..5d698f7 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplStandardBase.java
@@ -245,20 +245,6 @@
   }-*/;
 
   @Override
-  public native boolean isOrHasChild(Node parent, Node child) /*-{
-    while (child) {
-      if (parent == child) {
-        return true;
-      }
-      child = child.parentNode;
-      if (child && (child.nodeType != 1)) {
-        child = null;
-      }
-    }
-    return false;
-  }-*/;
-
-  @Override
   public void setScrollLeft(Document doc, int left) {
     // Safari always applies document scrolling to the body element, even in
     // strict mode.
diff --git a/user/src/com/google/gwt/dom/client/DOMImplTrident.java b/user/src/com/google/gwt/dom/client/DOMImplTrident.java
index 935d7c5..fe71941 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplTrident.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplTrident.java
@@ -27,6 +27,33 @@
    */
   private static EventTarget currentEventTarget;
 
+  static native boolean isOrHasChildImpl(Node parent, Node child) /*-{
+    // Element.contains() doesn't work with non-Element nodes on IE, so we have
+    // to deal explicitly with non-Element nodes here.
+
+    // Only Element (1) and Document (9) can contain other nodes.
+    if ((parent.nodeType != 1) && (parent.nodeType != 9)) {
+      return parent == child;
+    }
+
+    // If the child is not an Element, check its parent instead.
+    if (child.nodeType != 1) {
+      child = child.parentNode;
+      if (!child) {
+        return false;
+      }
+    }
+
+    if (parent.nodeType == 9) {
+      // In IE8 and IE9 (at least), document.contains does not exist, so use body.contains instead
+      return (parent === child) || (parent.body && parent.body.contains(child));
+    } else {
+      // An extra equality check is required due to the fact that
+      // elem.contains(elem) is false if elem is not attached to the DOM.
+      return (parent === child) || parent.contains(child);
+    }
+  }-*/;
+
   @Override
   public native ButtonElement createButtonElement(Document doc, String type) /*-{
     return doc.createElement("<BUTTON type='" + type + "'></BUTTON>");
@@ -253,27 +280,9 @@
   }-*/;
 
   @Override
-  public native boolean isOrHasChild(Node parent, Node child) /*-{
-    // Element.contains() doesn't work with non-Element nodes on IE, so we have
-    // to deal explicitly with non-Element nodes here.
-
-    // Only Element (1) and Document (9) can contain other nodes.
-    if ((parent.nodeType != 1) && (parent.nodeType != 9)) {
-      return parent == child;
-    }
-
-    // If the child is not an Element, check its parent instead.
-    if (child.nodeType != 1) {
-      child = child.parentNode;
-      if (!child) {
-        return false;
-      }
-    }
-
-    // An extra equality check is required due to the fact that
-    // elem.contains(elem) is false if elem is not attached to the DOM.
-    return (parent === child) || parent.contains(child);
-  }-*/;
+  public boolean isOrHasChild(Node parent, Node child) {
+    return isOrHasChildImpl(parent, child);
+  }
 
   @Override
   public native void selectAdd(SelectElement select, OptionElement option,
diff --git a/user/test/com/google/gwt/user/client/ui/DOMTest.java b/user/test/com/google/gwt/user/client/ui/DOMTest.java
index 17e09b9..c0b8510 100644
--- a/user/test/com/google/gwt/user/client/ui/DOMTest.java
+++ b/user/test/com/google/gwt/user/client/ui/DOMTest.java
@@ -17,17 +17,18 @@
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.dom.client.BodyElement;
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Text;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.junit.DoNotRunWith;
 import com.google.gwt.junit.Platform;
 import com.google.gwt.junit.client.GWTTestCase;
-import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.Timer;
@@ -83,6 +84,7 @@
    */
   public void testEventGetCurrentEventOnException() {
     Button button = new Button("test", new ClickHandler() {
+      @Override
       public void onClick(ClickEvent event) {
         // Intentionally trigger an error
         throw new IllegalArgumentException();
@@ -93,6 +95,7 @@
     // Verify the exception is captured
     final List<String> ret = new ArrayList<String>();
     GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
+      @Override
       public void onUncaughtException(Throwable e) {
         Event event = DOM.eventGetCurrentEvent();
         if (event == null) {
@@ -141,11 +144,12 @@
     DOM.setStyleAttribute(elem, "left", (left - doc.getBodyOffsetTop()) + "px");
 
     delayTestFinish(1000);
-    DeferredCommand.addCommand(new Command() {
+    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+        @Override
       public void execute() {
-        assertEquals(top + margin, DOM.getAbsoluteTop(elem));
-        assertEquals(left + margin, DOM.getAbsoluteLeft(elem));
-        finishTest();
+          assertEquals(top + margin, DOM.getAbsoluteTop(elem));
+          assertEquals(left + margin, DOM.getAbsoluteLeft(elem));
+          finishTest();
       }
     });
   }
@@ -269,20 +273,45 @@
    * across browsers.
    */
   public void testIsOrHasChild() {
+    Document doc = Document.get();
     Element div = DOM.createDiv();
     Element childDiv = DOM.createDiv();
+    Text text = Document.get().createTextNode("text");
 
-    assertFalse(DOM.isOrHasChild(div, childDiv));
-    assertTrue(DOM.isOrHasChild(div, div));
+    // unattached, not related
+    assertFalse(div.isOrHasChild(childDiv));
+    assertFalse(div.isOrHasChild(text));
+    assertTrue(div.isOrHasChild(div));
+    assertTrue(text.isOrHasChild(text));
+    assertFalse(doc.isOrHasChild(div));
+    assertFalse(doc.isOrHasChild(text));
+    assertFalse(div.isOrHasChild(doc));
+    assertFalse(text.isOrHasChild(doc));
 
-    DOM.appendChild(div, childDiv);
-    assertTrue(DOM.isOrHasChild(div, childDiv));
-    assertFalse(DOM.isOrHasChild(childDiv, div));
+    // unattached, related
+    div.appendChild(childDiv);
+    childDiv.appendChild(text);
+    assertTrue(div.isOrHasChild(childDiv));
+    assertTrue(childDiv.isOrHasChild(text));
+    assertFalse(childDiv.isOrHasChild(div));
+    assertFalse(text.isOrHasChild(childDiv));
+    assertFalse(doc.isOrHasChild(div));
+    assertFalse(doc.isOrHasChild(text));
+    assertFalse(div.isOrHasChild(doc));
+    assertFalse(text.isOrHasChild(doc));
 
+    // attached, related
     DOM.appendChild(RootPanel.getBodyElement(), div);
-    assertTrue(DOM.isOrHasChild(div, childDiv));
-    assertTrue(DOM.isOrHasChild(div, div));
-    assertFalse(DOM.isOrHasChild(childDiv, div));
+    assertTrue(div.isOrHasChild(childDiv));
+    assertTrue(childDiv.isOrHasChild(text));
+    assertTrue(div.isOrHasChild(div));
+    assertTrue(text.isOrHasChild(text));
+    assertFalse(childDiv.isOrHasChild(div));
+    assertFalse(text.isOrHasChild(childDiv));
+    assertTrue(doc.isOrHasChild(div));
+    assertTrue(doc.isOrHasChild(text));
+    assertFalse(div.isOrHasChild(Document.get()));
+    assertFalse(text.isOrHasChild(Document.get()));
   }
 
   /**