Fixes Issue #1218
Improves the speed for DOM.isOrHasChild by adding more browser
specialization. The techniques used are:
IE6/7 - Node.contains with special case for equality.
Safari - Tree walk (Node.contains broken on Safari2).
Mozilla - Node.compareDocumentPosition
Opera - Node.contains
Patch by: mmastrac, knorton
Review by: jgw, ecc
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1829 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
index 7902753..5dd4ba9 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplIE6.java
@@ -244,12 +244,9 @@
@Override
public native boolean isOrHasChild(Element parent, Element child) /*-{
- while (child) {
- if (parent.uniqueID == child.uniqueID)
- return true;
- child = child.parentElement;
- }
- 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.uniqueID == child.uniqueID) || parent.contains(child);
}-*/;
@Override
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java b/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java
index 055b0f7..72b18c6 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplMozilla.java
@@ -80,25 +80,9 @@
@Override
public native boolean isOrHasChild(Element parent, Element child) /*-{
- while (child) {
- if (parent.isSameNode(child)) {
- return true;
- }
-
- try {
- child = child.parentNode;
- } catch(e) {
- // Give up on 'Permission denied to get property
- // HTMLDivElement.parentNode'
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=208427
- return false;
- }
-
- if (child && (child.nodeType != 1)) {
- child = null;
- }
- }
- return false;
+ // For more information about compareDocumentPosition, see:
+ // http://www.quirksmode.org/blog/archives/2006/01/contains_for_mo.html
+ return parent.isSameNode(child) || !!(parent.compareDocumentPosition(child) & 16);
}-*/;
@Override
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java b/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java
index 5bad5b4..155e084 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplSafari.java
@@ -120,4 +120,18 @@
select.insertBefore(newOption, select.children[index]);
}
}-*/;
+
+ @Override
+ public native boolean isOrHasChild(Element parent, Element child) /*-{
+ while (child) {
+ if (parent == child) {
+ return true;
+ }
+ child = child.parentNode;
+ if (child && (child.nodeType != 1)) {
+ child = null;
+ }
+ }
+ return false;
+ }-*/;
}
diff --git a/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java b/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java
index 14367e7..64f0a73 100644
--- a/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java
+++ b/user/src/com/google/gwt/user/client/impl/DOMImplStandard.java
@@ -169,16 +169,7 @@
@Override
public native boolean isOrHasChild(Element parent, Element child) /*-{
- while (child) {
- if (parent == child) {
- return true;
- }
- child = child.parentNode;
- if (child && (child.nodeType != 1)) {
- child = null;
- }
- }
- return false;
+ return parent.contains(child);
}-*/;
@Override
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 b2904cc..195d813 100644
--- a/user/test/com/google/gwt/user/client/ui/DOMTest.java
+++ b/user/test/com/google/gwt/user/client/ui/DOMTest.java
@@ -167,10 +167,18 @@
public void testIsOrHasChild() {
Element div = DOM.createDiv();
Element childDiv = DOM.createDiv();
+
assertFalse(DOM.isOrHasChild(div, childDiv));
+ assertTrue(DOM.isOrHasChild(div, div));
+
DOM.appendChild(div, childDiv);
assertTrue(DOM.isOrHasChild(div, childDiv));
assertFalse(DOM.isOrHasChild(childDiv, div));
+
+ DOM.appendChild(RootPanel.getBodyElement(), div);
+ assertTrue(DOM.isOrHasChild(div, childDiv));
+ assertTrue(DOM.isOrHasChild(div, div));
+ assertFalse(DOM.isOrHasChild(childDiv, div));
}
/**