Change the binding parent for native anonymous content to work like the binding parent for XBL anonymous content, and be the parent of the anonymous content subtree rather than the root of the anonymous content subtree. (Bug 436453) r=bzbarsky,smaug,surkov sr=bzbarsky
authorL. David Baron <dbaron@dbaron.org>
Tue, 22 Jul 2008 21:50:20 -0700
changeset 16126 ce6c804304009ee2324d941d7dce21b55ba8750d
parent 16125 bf06d3308793a8aa6ce126ab23816c77b3ce8e2e
child 16127 ba8e7ded433b37e2f2a2fa0efc1c2dfb54b467fd
push id786
push userdbaron@mozilla.com
push dateWed, 23 Jul 2008 04:50:58 +0000
treeherdermozilla-central@80865e03f6af [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky, smaug, surkov, bzbarsky
bugs436453
milestone1.9.1a1pre
Change the binding parent for native anonymous content to work like the binding parent for XBL anonymous content, and be the parent of the anonymous content subtree rather than the root of the anonymous content subtree. (Bug 436453) r=bzbarsky,smaug,surkov sr=bzbarsky
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessibilityUtils.cpp
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsDocAccessible.cpp
accessible/src/html/nsHyperTextAccessible.cpp
content/base/public/nsIContent.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericElement.cpp
content/events/src/nsDOMEvent.cpp
content/xbl/src/nsBindingManager.cpp
content/xbl/src/nsXBLService.cpp
content/xul/content/src/nsXULElement.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/html/nsHTMLAnonymousUtils.cpp
editor/libeditor/html/nsHTMLEditor.cpp
embedding/components/find/src/nsFind.cpp
embedding/components/find/src/nsWebBrowserFind.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsPresShell.cpp
layout/generic/nsBRFrame.cpp
layout/generic/nsFrame.cpp
layout/inspector/src/inDOMView.cpp
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -186,18 +186,17 @@ NS_IMETHODIMP nsAccessNode::Init()
     do_QueryInterface(docAccessible);
   NS_ASSERTION(privateDocAccessible, "No private docaccessible for docaccessible");
   privateDocAccessible->CacheAccessNode(uniqueID, this);
 
   // Make sure an ancestor in real content is cached
   // so that nsDocAccessible::RefreshNodes() can find the anonymous subtree to release when
   // the root node goes away
   nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
-  if (content && (content->IsNativeAnonymous() ||
-                  content->GetBindingParent())) {
+  if (content && content->IsInAnonymousSubtree()) {
     // Specific examples of where this is used: <input type="file"> and <xul:findbar>
     nsCOMPtr<nsIAccessible> parentAccessible;
     docAccessible->GetAccessibleInParentChain(mDOMNode, PR_TRUE, getter_AddRefs(parentAccessible));
     if (parentAccessible) {
       PRInt32 childCountUnused;
       parentAccessible->GetChildCount(&childCountUnused);
     }
   }
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -791,17 +791,17 @@ nsAccUtils::FindNeighbourPointingToNode(
                                         PRUint32 aAttrNum,
                                         nsIAtom *aTagName,
                                         PRUint32 aAncestorLevelsToSearch)
 {
   nsCOMPtr<nsIContent> binding;
   nsAutoString controlID;
   if (!nsAccUtils::GetID(aForNode, controlID)) {
     binding = aForNode->GetBindingParent();
-    if (binding == aForNode)
+    if (aForNode->IsRootOfNativeAnonymousSubtree()) // XXX Was this the intent?
       return nsnull;
 
     aForNode->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::anonid, controlID);
     if (controlID.IsEmpty())
       return nsnull;
   }
 
   // Look for label in subtrees of nearby ancestors
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -1936,16 +1936,17 @@ nsresult nsAccessible::GetXULName(nsAStr
   label.CompressWhitespace();
   if (!label.IsEmpty()) {
     aLabel = label;
     return NS_OK;
   }
 
   // Can get text from title of <toolbaritem> if we're a child of a <toolbaritem>
   nsIContent *bindingParent = content->GetBindingParent();
+  // XXXldb: Why do we skip to bindingParent's parent?
   nsIContent *parent = bindingParent? bindingParent->GetParent() :
                                       content->GetParent();
   while (parent) {
     if (parent->Tag() == nsAccessibilityAtoms::toolbaritem &&
         parent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::title, label)) {
       label.CompressWhitespace();
       aLabel = label;
       return NS_OK;
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1755,19 +1755,18 @@ void nsDocAccessible::RefreshNodes(nsIDO
         children->GetLength(&childCount);
       nsCOMPtr<nsIDOMNode> possibleAnonNode;
       for (PRUint32 index = 0; index < childCount; index++) {
         nsCOMPtr<nsIAccessNode> childAccessNode;
         children->QueryElementAt(index, NS_GET_IID(nsIAccessNode),
                                  getter_AddRefs(childAccessNode));
         childAccessNode->GetDOMNode(getter_AddRefs(possibleAnonNode));
         nsCOMPtr<nsIContent> iterContent = do_QueryInterface(possibleAnonNode);
-        if (iterContent && (iterContent->IsNativeAnonymous() ||
-                            iterContent->GetBindingParent())) {
-          // GetBindingParent() check is a perf win -- make sure we don't
+        if (iterContent && iterContent->IsInAnonymousSubtree()) {
+          // IsInAnonymousSubtree() check is a perf win -- make sure we don't
           // shut down the same subtree twice since we'll reach non-anon content via
           // DOM traversal later in this method
           RefreshNodes(possibleAnonNode);
         }
       }
     }
   }
 
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -635,17 +635,19 @@ nsresult nsHyperTextAccessible::DOMPoint
   // Get accessible for this findNode, or if that node isn't accessible, use the
   // accessible for the next DOM node which has one (based on forward depth first search)
   nsCOMPtr<nsIAccessible> descendantAccessible;
   if (findNode) {
     nsCOMPtr<nsIContent> findContent = do_QueryInterface(findNode);
     if (findContent->IsNodeOfType(nsINode::eHTML) && 
         findContent->NodeInfo()->Equals(nsAccessibilityAtoms::br)) {
       nsIContent *parent = findContent->GetParent();
-      if (parent && parent->IsNativeAnonymous() && parent->GetChildCount() == 1) {
+      if (parent &&
+          parent->IsRootOfNativeAnonymousSubtree() &&
+          parent->GetChildCount() == 1) {
         // This <br> is the only node in a text control, therefore it is the hacky
         // "bogus node" used when there is no text in a control
         *aHyperTextOffset = 0;
         return NS_OK;
       }
     }
     descendantAccessible = GetFirstAvailableAccessible(findNode);
   }
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -141,17 +141,17 @@ public:
     return GetCurrentDoc();
   }
 
   /**
    * Get whether this content is C++-generated anonymous content
    * @see nsIAnonymousContentCreator
    * @return whether this content is anonymous
    */
-  PRBool IsNativeAnonymous() const
+  PRBool IsRootOfNativeAnonymousSubtree() const
   {
     return HasFlag(NODE_IS_ANONYMOUS);
   }
 
   /**
    * Makes this content anonymous
    * @see nsIAnonymousContentCreator
    */
@@ -172,29 +172,54 @@ public:
   PRBool IsInNativeAnonymousSubtree() const
   {
 #ifdef DEBUG
     if (HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE)) {
       return PR_TRUE;
     }
     nsIContent* content = GetBindingParent();
     while (content) {
-      if (content->IsNativeAnonymous()) {
+      if (content->IsRootOfNativeAnonymousSubtree()) {
         NS_ERROR("Element not marked to be in native anonymous subtree!");
         break;
       }
       content = content->GetBindingParent();
     }
     return PR_FALSE;
 #else
     return HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE);
 #endif
   }
 
   /**
+   * Returns true if and only if this node has a parent, but is not in
+   * its parent's child list.
+   */
+  PRBool IsRootOfAnonymousSubtree() const
+  {
+    NS_ASSERTION(!IsRootOfNativeAnonymousSubtree() ||
+                 (GetParent() && GetBindingParent() == GetParent()),
+                 "root of native anonymous subtree must have parent equal "
+                 "to binding parent");
+    nsIContent *bindingParent = GetBindingParent();
+    return bindingParent && bindingParent == GetParent();
+  }
+
+  /**
+   * Returns true if and only if there is NOT a path through child lists
+   * from the top of this node's parent chain back to this node.
+   */
+  PRBool IsInAnonymousSubtree() const
+  {
+    NS_ASSERTION(!IsInNativeAnonymousSubtree() || GetBindingParent(),
+                 "must have binding parent when in native anonymous subtree");
+    return GetBindingParent() != nsnull;
+  }
+
+  /**
    * Get the namespace that this element's tag is defined in
    * @return the namespace
    */
   PRInt32 GetNameSpaceID() const
   {
     return mNodeInfo->NamespaceID();
   }
 
@@ -558,19 +583,22 @@ public:
       editableAncestor = parent;
     // This is in another editable content, use the result of it.
     if (editableAncestor)
       return editableAncestor->GetDesiredIMEState();
     return IME_STATUS_ENABLE;
   }
 
   /**
-   * Gets content node with the binding responsible for our construction (and
-   * existence).  Used by anonymous content (XBL-generated). null for all
-   * explicit content.
+   * Gets content node with the binding (or native code, possibly on the
+   * frame) responsible for our construction (and existence).  Used by
+   * anonymous content (both XBL-generated and native-anonymous).
+   *
+   * null for all explicit content (i.e., content reachable from the top
+   * of its GetParent() chain via child lists).
    *
    * @return the binding parent
    */
   virtual nsIContent *GetBindingParent() const = 0;
 
   /**
    * Get the base URI for any relative URIs within this piece of
    * content. Generally, this is the document's base URI, but certain
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1885,17 +1885,17 @@ nsContentUtils::GenerateStateKey(nsICont
     KeyAppendInt(aID, aKey);
     return NS_OK;
   }
 
   // We must have content if we're not using a special state id
   NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
 
   // Don't capture state for anonymous content
-  if (aContent->IsNativeAnonymous() || aContent->GetBindingParent()) {
+  if (aContent->IsInAnonymousSubtree()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aContent));
   if (element && IsAutocompleteOff(element)) {
     return NS_OK;
   }
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2140,18 +2140,18 @@ nsDocument::ElementFromPoint(PRInt32 aX,
     return NS_OK;
   }
 
   // If we have an anonymous element (such as an internal div from a textbox),
   // or a node that isn't an element (such as a text frame node),
   // replace it with the first non-anonymous parent node of type element.
   while (ptContent &&
          !ptContent->IsNodeOfType(nsINode::eELEMENT) ||
-         ptContent->GetBindingParent() ||
-         ptContent->IsNativeAnonymous()) {
+         ptContent->IsInAnonymousSubtree()) {
+    // XXXldb: Faster to jump to GetBindingParent if non-null?
     ptContent = ptContent->GetParent();
   }
  
   if (ptContent)
     CallQueryInterface(ptContent, aReturn);
   return NS_OK;
 }
 
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -587,36 +587,40 @@ nsGenericDOMDataNode::BindToTree(nsIDocu
   // only assert if our parent is _changing_ while we have a parent.
   NS_PRECONDITION(!GetParent() || aParent == GetParent(),
                   "Already have a parent.  Unbind first!");
   NS_PRECONDITION(!GetBindingParent() ||
                   aBindingParent == GetBindingParent() ||
                   (!aBindingParent && aParent &&
                    aParent->GetBindingParent() == GetBindingParent()),
                   "Already have a binding parent.  Unbind first!");
-  NS_PRECONDITION(aBindingParent != this || IsNativeAnonymous(),
-                  "Only native anonymous content should have itself as its "
+  NS_PRECONDITION(aBindingParent != this,
+                  "Content must not be its own binding parent");
+  NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() || 
+                  aBindingParent == aParent,
+                  "Native anonymous content must have its parent as its "
                   "own binding parent");
 
   if (!aBindingParent && aParent) {
     aBindingParent = aParent->GetBindingParent();
   }
 
   // First set the binding parent
   if (aBindingParent) {
     nsDataSlots *slots = GetDataSlots();
     NS_ENSURE_TRUE(slots, NS_ERROR_OUT_OF_MEMORY);
 
-    NS_ASSERTION(IsNativeAnonymous() || !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
+    NS_ASSERTION(IsRootOfNativeAnonymousSubtree() ||
+                 !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
                  aBindingParent->IsInNativeAnonymousSubtree(),
                  "Trying to re-bind content from native anonymous subtree to"
                  "non-native anonymous parent!");
     slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
-    if (IsNativeAnonymous() ||
-        aBindingParent->IsInNativeAnonymousSubtree()) {
+    if (IsRootOfNativeAnonymousSubtree() ||
+        aParent->IsInNativeAnonymousSubtree()) {
       SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
     }
   }
 
   // Set parent
   if (aParent) {
     mParentPtrBits =
       reinterpret_cast<PtrBits>(aParent) | PARENT_BIT_PARENT_IS_CONTENT;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -430,28 +430,25 @@ nsIContent::UpdateEditableState()
 
   SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
 }
 
 nsIContent*
 nsIContent::FindFirstNonNativeAnonymous() const
 {
   // This handles also nested native anonymous content.
-  nsIContent* content = GetBindingParent();
-  nsIContent* possibleResult = 
-    !IsNativeAnonymous() ? const_cast<nsIContent*>(this) : nsnull;
-  while (content) {
-    if (content->IsNativeAnonymous()) {
-      content = possibleResult = content->GetParent();
-    } else {
-      content = content->GetBindingParent();
+  for (const nsIContent *content = this; content;
+       content = content->GetBindingParent()) {
+    if (!content->IsInNativeAnonymousSubtree()) {
+      // Oops, this function signature allows casting const to
+      // non-const.  (Then again, so does GetChildAt(0)->GetParent().)
+      return const_cast<nsIContent*>(content);
     }
   }
-
-  return possibleResult;
+  return nsnull;
 }
 
 //----------------------------------------------------------------------
 
 nsChildContentList::~nsChildContentList()
 {
   MOZ_COUNT_DTOR(nsChildContentList);
 }
@@ -2086,21 +2083,21 @@ nsGenericElement::BindToTree(nsIDocument
   NS_PRECONDITION(!GetBindingParent() ||
                   aBindingParent == GetBindingParent() ||
                   (!aBindingParent && aParent &&
                    aParent->GetBindingParent() == GetBindingParent()),
                   "Already have a binding parent.  Unbind first!");
   NS_PRECONDITION(!aParent || !aDocument ||
                   !aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
                   "Parent in document but flagged as forcing XBL");
-  NS_PRECONDITION(aBindingParent != this || IsNativeAnonymous(),
-                  "Only native anonymous content should have itself as its "
-                  "own binding parent");
-  NS_PRECONDITION(!IsNativeAnonymous() || aBindingParent == this,
-                  "Native anonymous content must have itself as its "
+  NS_PRECONDITION(aBindingParent != this,
+                  "Content must not be its own binding parent");
+  NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
+                  aBindingParent == aParent,
+                  "Native anonymous content must have its parent as its "
                   "own binding parent");
 
   if (!aBindingParent && aParent) {
     aBindingParent = aParent->GetBindingParent();
   }
 
 #ifdef MOZ_XUL
   // First set the binding parent
@@ -2116,23 +2113,23 @@ nsGenericElement::BindToTree(nsIDocument
 
       if (!slots) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
       slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
     }
   }
-  NS_ASSERTION(!aBindingParent || IsNativeAnonymous() ||
+  NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
                !HasFlag(NODE_IS_IN_ANONYMOUS_SUBTREE) ||
                aBindingParent->IsInNativeAnonymousSubtree(),
                "Trying to re-bind content from native anonymous subtree to"
                "non-native anonymous parent!");
-  if (IsNativeAnonymous() ||
-      aBindingParent && aBindingParent->IsInNativeAnonymousSubtree()) {
+  if (IsRootOfNativeAnonymousSubtree() ||
+      aParent && aParent->IsInNativeAnonymousSubtree()) {
     SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
   }
 
   PRBool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
 
   // Now set the parent and set the "Force attach xbl" flag if needed.
   if (aParent) {
     mParentPtrBits = reinterpret_cast<PtrBits>(aParent) | PARENT_BIT_PARENT_IS_CONTENT;
@@ -2297,33 +2294,33 @@ nsGenericElement::PreHandleEvent(nsEvent
 }
 
 static nsIContent*
 FindNativeAnonymousSubtreeOwner(nsIContent* aContent)
 {
   if (aContent->IsInNativeAnonymousSubtree()) {
     PRBool isNativeAnon = PR_FALSE;
     while (aContent && !isNativeAnon) {
-      isNativeAnon = aContent->IsNativeAnonymous();
+      isNativeAnon = aContent->IsRootOfNativeAnonymousSubtree();
       aContent = aContent->GetParent();
     }
   }
   return aContent;
 }
 
 nsresult
 nsGenericElement::doPreHandleEvent(nsIContent* aContent,
                                    nsEventChainPreVisitor& aVisitor)
 {
   //FIXME! Document how this event retargeting works, Bug 329124.
   aVisitor.mCanHandle = PR_TRUE;
 
   // Don't propagate mouseover and mouseout events when mouse is moving
   // inside native anonymous content.
-  PRBool isAnonForEvents = aContent->IsNativeAnonymous();
+  PRBool isAnonForEvents = aContent->IsRootOfNativeAnonymousSubtree();
   if ((aVisitor.mEvent->message == NS_MOUSE_ENTER_SYNTH ||
        aVisitor.mEvent->message == NS_MOUSE_EXIT_SYNTH) &&
       // This is an optimization - try to stop event propagation when
       // event has just possibly been retargeted.
       static_cast<nsISupports*>(aContent) == aVisitor.mEvent->target) {
      nsCOMPtr<nsIContent> relatedTarget =
        do_QueryInterface(static_cast<nsMouseEvent*>
                                     (aVisitor.mEvent)->relatedTarget);
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -129,20 +129,18 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aP
     mEvent->time = PR_Now();
   }
 
   // Get the explicit original target (if it's anonymous make it null)
   {
     mExplicitOriginalTarget = GetTargetFromFrame();
     mTmpRealOriginalTarget = mExplicitOriginalTarget;
     nsCOMPtr<nsIContent> content = do_QueryInterface(mExplicitOriginalTarget);
-    if (content) {
-      if (content->IsNativeAnonymous() || content->GetBindingParent()) {
-        mExplicitOriginalTarget = nsnull;
-      }
+    if (content && content->IsInAnonymousSubtree()) {
+      mExplicitOriginalTarget = nsnull;
     }
   }
 }
 
 nsDOMEvent::~nsDOMEvent() 
 {
   NS_ASSERT_OWNINGTHREAD(nsDOMEvent);
 
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -1258,25 +1258,21 @@ nsBindingManager::WalkRules(nsStyleSet* 
       if (content != aData->mContent) {
         if (!binding->InheritsStyle()) {
           // Go no further; we're not inheriting style from anything above here
           break;
         }
       }
     }
 
-    nsIContent* parent = content->GetBindingParent();
-    if (parent == content) {
-      NS_ASSERTION(content->IsNativeAnonymous(), "Unexpected binding parent");
-                             
-      break; // The anonymous content case is often deliberately hacked to
-             // return itself to cut off style inheritance here.  Do that.
+    if (content->IsRootOfNativeAnonymousSubtree()) {
+      break; // Deliberately cut off style inheritance here.
     }
 
-    content = parent;
+    content = content->GetBindingParent();
   } while (content);
 
   // If "content" is non-null that means we cut off inheritance at some point
   // in the loop.
   *aCutOffInheritance = (content != nsnull);
 
   // Null out the scoped root that we set repeatedly
   aData->mScopedRoot = nsnull;
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -105,21 +105,20 @@ IsAncestorBinding(nsIDocument* aDocument
                   nsIURI* aChildBindingURI,
                   nsIContent* aChild)
 {
   NS_ASSERTION(aDocument, "expected a document");
   NS_ASSERTION(aChildBindingURI, "expected a binding URI");
   NS_ASSERTION(aChild, "expected a child content");
 
   PRUint32 bindingRecursion = 0;
-  nsIContent* bindingParent = aChild->GetBindingParent();
   nsBindingManager* bindingManager = aDocument->BindingManager();
-  for (nsIContent* prev = aChild;
-       bindingParent && prev != bindingParent;
-       prev = bindingParent, bindingParent = bindingParent->GetBindingParent()) {
+  for (nsIContent *bindingParent = aChild->GetBindingParent();
+       bindingParent;
+       bindingParent = bindingParent->GetBindingParent()) {
     nsXBLBinding* binding = bindingManager->GetBinding(bindingParent);
     if (!binding) {
       continue;
     }
     PRBool equal;
     nsresult rv =
       binding->PrototypeBinding()->BindingURI()->Equals(aChildBindingURI,
                                                         &equal);
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1081,16 +1081,17 @@ nsXULElement::UnregisterAccessKey(const 
 
         if (shell) {
             nsIContent *content = this;
 
             // find out what type of content node this is
             if (mNodeInfo->Equals(nsGkAtoms::label)) {
                 // For anonymous labels the unregistering must
                 // occur on the binding parent control.
+                // XXXldb: And what if the binding parent is null?
                 content = GetBindingParent();
             }
 
             if (content) {
                 shell->GetPresContext()->EventStateManager()->
                     UnregisterAccessKey(content, aOldValue.First());
             }
         }
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -435,17 +435,17 @@ nsEditor::GetDesiredSpellCheckState()
   }
 
   // Check DOM state
   nsCOMPtr<nsIContent> content = do_QueryInterface(GetRoot());
   if (!content) {
     return PR_FALSE;
   }
 
-  if (content->IsNativeAnonymous()) {
+  if (content->IsRootOfNativeAnonymousSubtree()) {
     content = content->GetParent();
   }
 
   nsCOMPtr<nsIDOMNSHTMLElement> element = do_QueryInterface(content);
   if (!element) {
     return PR_FALSE;
   }
 
@@ -5236,17 +5236,17 @@ nsEditor::GetPIDOMEventTarget()
 
   nsIDOMElement *rootElement = GetRoot();
 
   // Now hack to make sure we are not anonymous content.
   // If we are grab the parent of root element for our observer.
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(rootElement);
 
-  if (content && content->IsNativeAnonymous())
+  if (content && content->IsRootOfNativeAnonymousSubtree())
   {
     mEventTarget = do_QueryInterface(content->GetParent());
     piTarget = mEventTarget;
     NS_IF_ADDREF(piTarget);
   }
   else
   {
     // Don't use getDocument here, because we have no way of knowing
--- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
@@ -183,17 +183,17 @@ nsHTMLEditor::CreateAnonymousElement(con
     if (NS_FAILED(res)) return res;
   }
 
   {
     nsAutoScriptBlocker scriptBlocker;
 
     // establish parenthood of the element
     newContent->SetNativeAnonymous();
-    res = newContent->BindToTree(doc, parentContent, newContent, PR_TRUE);
+    res = newContent->BindToTree(doc, parentContent, parentContent, PR_TRUE);
     if (NS_FAILED(res)) {
       newContent->UnbindFromTree();
       return res;
     }
   }
 
   nsElementDeletionObserver* observer =
     new nsElementDeletionObserver(newContent, parentContent);
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -5923,17 +5923,17 @@ nsHTMLEditor::GetSelectionContainer(nsID
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLEditor::IsAnonymousElement(nsIDOMElement * aElement, PRBool * aReturn)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
-  *aReturn = content->IsNativeAnonymous();
+  *aReturn = content->IsRootOfNativeAnonymousSubtree();
   return NS_OK;
 }
 
 nsresult
 nsHTMLEditor::SetReturnInParagraphCreatesNewParagraph(PRBool aCreatesNewParagraph)
 {
   mCRInParagraphCreatesParagraph = aCreatesNewParagraph;
   return NS_OK;
--- a/embedding/components/find/src/nsFind.cpp
+++ b/embedding/components/find/src/nsFind.cpp
@@ -361,17 +361,17 @@ nsFindContentIterator::MaybeSetupInnerIt
 }
 
 void
 nsFindContentIterator::SetupInnerIterator(nsIContent* aContent)
 {
   if (!aContent) {
     return;
   }
-  NS_ASSERTION(!aContent->IsNativeAnonymous(), "invalid call");
+  NS_ASSERTION(!aContent->IsRootOfNativeAnonymousSubtree(), "invalid call");
 
   nsIDocument* doc = aContent->GetDocument();
   nsIPresShell* shell = doc ? doc->GetPrimaryShell() : nsnull;
   if (!shell)
     return;
 
   nsIFrame* frame = shell->GetPrimaryFrameFor(aContent);
   if (!frame)
--- a/embedding/components/find/src/nsWebBrowserFind.cpp
+++ b/embedding/components/find/src/nsWebBrowserFind.cpp
@@ -406,31 +406,16 @@ FocusElementButNotDocument(nsIDocument* 
   aDocument->EndUpdate(UPDATE_CONTENT_STATE);
 
   // Reset esm::mCurrentFocus = nsnull for this doc, so when this document
   // does get focus next time via preHandleEvent() NS_GOTFOCUS,
   // the old document gets blurred
   esm->SetFocusedContent(nsnull);
 }
 
-static PRBool
-IsInNativeAnonymousSubtree(nsIContent* aContent)
-{
-    while (aContent) {
-        nsIContent* bindingParent = aContent->GetBindingParent();
-        if (bindingParent == aContent) {
-            return PR_TRUE;
-        }
-
-        aContent = bindingParent;
-    }
-
-    return PR_FALSE;
-}
-
 void nsWebBrowserFind::SetSelectionAndScroll(nsIDOMWindow* aWindow,
                                              nsIDOMRange*  aRange)
 {
   nsCOMPtr<nsIDOMDocument> domDoc;    
   aWindow->GetDocument(getter_AddRefs(domDoc));
   if (!domDoc) return;
 
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
@@ -446,17 +431,17 @@ void nsWebBrowserFind::SetSelectionAndSc
   nsCOMPtr<nsISelectionController> selCon;
   frame->GetSelectionController(presShell->GetPresContext(),
                                 getter_AddRefs(selCon));
   
   // since the match could be an anonymous textnode inside a
   // <textarea> or text <input>, we need to get the outer frame
   nsITextControlFrame *tcFrame = nsnull;
   for ( ; content; content = content->GetParent()) {
-    if (!IsInNativeAnonymousSubtree(content)) {
+    if (!content->IsInNativeAnonymousSubtree()) {
       nsIFrame* f = presShell->GetPrimaryFrameFor(content);
       if (!f)
         return;
       CallQueryInterface(f, &tcFrame);
       break;
     }
   }
 
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1910,18 +1910,19 @@ nsCSSFrameConstructor::CreateAttributeCo
   nsCOMPtr<nsIContent> content;
   nsresult rv = NS_NewAttributeContent(mDocument->NodeInfoManager(),
                                        aAttrNamespace, aAttrName,
                                        getter_AddRefs(content));
   NS_ENSURE_SUCCESS(rv, rv);
 
   content->SetNativeAnonymous();
 
-  // Set aContent as the parent content so that event handling works.
-  rv = content->BindToTree(mDocument, aParentContent, content, PR_TRUE);
+  // Set aParentContent as the parent content so that event handling works.
+  // It is also the binding parent.
+  rv = content->BindToTree(mDocument, aParentContent, aParentContent, PR_TRUE);
   if (NS_FAILED(rv)) {
     content->UnbindFromTree();
     return rv;
   }
 
   // Create a text frame and initialize it
   nsIFrame* textFrame = NS_NewTextFrame(mPresShell, aStyleContext);
   rv = textFrame->Init(content, aParentFrame, nsnull);
@@ -1980,21 +1981,18 @@ nsCSSFrameConstructor::CreateGeneratedFr
 
     nsresult rv = NS_NewGenConImageContent(getter_AddRefs(content), nodeInfo,
                                            data.mContent.mImage);
     NS_ENSURE_SUCCESS(rv, rv);
 
     content->SetNativeAnonymous();
   
     // Set aContent as the parent content and set the document object. This
-    // way event handling works
-    // Hack the binding parent to make document rules not match (not
-    // like it matters, since we already have a non-element style
-    // context... which is totally wacky, but anyway).
-    rv = content->BindToTree(mDocument, aContent, content, PR_TRUE);
+    // way event handling works.  It is also the binding parent.
+    rv = content->BindToTree(mDocument, aContent, aContent, PR_TRUE);
     if (NS_FAILED(rv)) {
       content->UnbindFromTree();
       return rv;
     }
     
     // Create an image frame and initialize it
     nsIFrame* imageFrame = NS_NewImageFrame(mPresShell, aStyleContext);
     if (NS_UNLIKELY(!imageFrame)) {
@@ -2164,17 +2162,17 @@ nsCSSFrameConstructor::CreateGeneratedFr
         if (textPtr) {
           *textPtr = do_QueryInterface(textContent);
           NS_ASSERTION(*textPtr, "must implement nsIDOMCharacterData");
         }
 
         textContent->SetNativeAnonymous();
 
         // Set aContent as the parent content so that event handling works.
-        nsresult rv = textContent->BindToTree(mDocument, aContent, textContent,
+        nsresult rv = textContent->BindToTree(mDocument, aContent, aContent,
                                               PR_TRUE);
         if (NS_FAILED(rv)) {
           textContent->UnbindFromTree();
           return rv;
         }
 
         // Create a text frame and initialize it
         textFrame = NS_NewTextFrame(mPresShell, aStyleContext);
@@ -3401,17 +3399,18 @@ IsSpecialContent(nsIContent*     aConten
       aTag == nsGkAtoms::treecol ||
       aTag == nsGkAtoms::text ||
       aTag == nsGkAtoms::description ||
       aTag == nsGkAtoms::label ||
       aTag == nsGkAtoms::menu ||
       aTag == nsGkAtoms::menuitem ||
       aTag == nsGkAtoms::menubutton ||
       aTag == nsGkAtoms::menubar ||
-      (aTag == nsGkAtoms::popupgroup && aContent->IsNativeAnonymous()) ||
+      (aTag == nsGkAtoms::popupgroup &&
+       aContent->IsRootOfNativeAnonymousSubtree()) ||
       aTag == nsGkAtoms::iframe ||
       aTag == nsGkAtoms::editor ||
       aTag == nsGkAtoms::browser ||
       aTag == nsGkAtoms::progressmeter ||
 #endif
       aTag == nsGkAtoms::slider ||
       aTag == nsGkAtoms::scrollbar ||
       aTag == nsGkAtoms::scrollbarbutton ||
@@ -5694,30 +5693,27 @@ nsCSSFrameConstructor::CreateAnonymousFr
   nsPseudoFrames priorPseudoFrames; 
   aState.mPseudoFrames.Reset(&priorPseudoFrames);
 
   for (PRUint32 i=0; i < count; i++) {
     // get our child's content and set its parent to our content
     nsIContent* content = newAnonymousItems[i];
     NS_ASSERTION(content, "null anonymous content?");
 
-    nsIContent* bindingParent = content;
 #ifdef MOZ_SVG
     // least-surprise CSS binding until we do the SVG specified
     // cascading rules for <svg:use> - bug 265894
-    if (aParent &&
-        aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG)) {
-      bindingParent = aParent;
-    } else
+    if (!aParent ||
+        !aParent->NodeInfo()->Equals(nsGkAtoms::use, kNameSpaceID_SVG))
 #endif
     {
       content->SetNativeAnonymous();
     }
 
-    rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE);
+    rv = content->BindToTree(aDocument, aParent, aParent, PR_TRUE);
     if (NS_FAILED(rv)) {
       content->UnbindFromTree();
       return rv;
     }
 
     nsIFrame* newFrame = creator->CreateFrameFor(content);
     if (newFrame) {
       aChildItems.AddChild(newFrame);
@@ -5907,17 +5903,18 @@ nsCSSFrameConstructor::ConstructXULFrame
         if (isRootChromeShell) {
           *aHaltProcessing = PR_TRUE;
           return NS_OK;
         }
   #endif
 
         newFrame = NS_NewMenuBarFrame(mPresShell, aStyleContext);
       }
-      else if (aTag == nsGkAtoms::popupgroup && aContent->IsNativeAnonymous()) {
+      else if (aTag == nsGkAtoms::popupgroup &&
+               aContent->IsRootOfNativeAnonymousSubtree()) {
         // This frame contains child popups
         newFrame = NS_NewPopupSetFrame(mPresShell, aStyleContext);
       }
       else if (aTag == nsGkAtoms::iframe || aTag == nsGkAtoms::editor ||
                aTag == nsGkAtoms::browser) {
         newFrame = NS_NewSubDocumentFrame(mPresShell, aStyleContext);
       }
       // PROGRESS METER CONSTRUCTION
@@ -6169,17 +6166,18 @@ nsCSSFrameConstructor::ConstructXULFrame
     // don't support floating or positioning of XUL frames.
     rv = aState.AddChild(topFrame, aFrameItems, aContent, aStyleContext,
                          origParentFrame, PR_FALSE, PR_FALSE, isPopup);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
 #ifdef MOZ_XUL
-    if (aTag == nsGkAtoms::popupgroup && aContent->IsNativeAnonymous()) {
+    if (aTag == nsGkAtoms::popupgroup &&
+        aContent->IsRootOfNativeAnonymousSubtree()) {
       nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
       if (rootBox) {
         NS_ASSERTION(rootBox->GetPopupSetFrame() == newFrame,
                      "Unexpected PopupSetFrame");
         aState.mPopupItems.containingBlock = rootBox->GetPopupSetFrame();
       }      
     }
 #endif
@@ -10564,23 +10562,25 @@ nsCSSFrameConstructor::ReplicateFixedFra
   docRootFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList);
   return NS_OK;
 }
 
 static PRBool
 IsBindingAncestor(nsIContent* aContent, nsIContent* aBindingRoot)
 {
   while (PR_TRUE) {
+    // Native-anonymous content doesn't contain insertion points, so
+    // we don't need to search through it.
+    if (aContent->IsRootOfNativeAnonymousSubtree())
+      return PR_FALSE;
     nsIContent* bindingParent = aContent->GetBindingParent();
     if (!bindingParent)
       return PR_FALSE;
     if (bindingParent == aBindingRoot)
       return PR_TRUE;
-    if (bindingParent == aContent)
-      return PR_FALSE;
     aContent = bindingParent;
   }
 }
 
 // Helper function that searches the immediate child frames 
 // (and their children if the frames are "special")
 // for a frame that maps the specified content object
 nsIFrame*
@@ -10668,16 +10668,18 @@ nsCSSFrameConstructor::FindFrameWithCont
 
         // only do this if there is content
         if (kidContent) {
           // We search the immediate children only, but if the child frame has
           // the same content pointer as its parent then we need to search its
           // child frames, too.
           // We also need to search if the child content is anonymous and scoped
           // to the parent content.
+          // XXXldb What makes us continue the search once we're inside
+          // the anonymous subtree?
           if (aParentContent == kidContent ||
               (aParentContent && IsBindingAncestor(kidContent, aParentContent))) 
           {
 #ifdef NOISY_FINDFRAME
             FFWC_recursions++;
             printf("  recursing with new parent set to kidframe=%p, parentContent=%p\n", 
                    kidFrame, aParentContent);
 #endif
@@ -11647,17 +11649,17 @@ nsCSSFrameConstructor::CreateFloatingLet
   nsIFrame* letterFrame;
   nsStyleSet *styleSet = mPresShell->StyleSet();
 
   letterFrame = NS_NewFirstLetterFrame(mPresShell, aStyleContext);
   // We don't want to use a text content for a non-text frame (because we want
   // its primary frame to be a text frame).  So use its parent for the
   // first-letter.
   nsIContent* letterContent = aTextContent->GetParent();
-  NS_ASSERTION(letterContent->GetBindingParent() != letterContent,
+  NS_ASSERTION(!letterContent->IsRootOfNativeAnonymousSubtree(),
                "Reframes of this letter frame will mess with the root of a "
                "native anonymous content subtree!");
   InitAndRestoreFrame(aState, letterContent,
                       aState.GetGeometricParent(aStyleContext->GetStyleDisplay(),
                                                 aParentFrame),
                       nsnull, letterFrame);
 
   // Init the text frame to refer to the letter frame. Make sure we
@@ -11772,17 +11774,17 @@ nsCSSFrameConstructor::CreateLetterFrame
       // Make an inflow first-letter frame
       nsIFrame* letterFrame = NS_NewFirstLetterFrame(mPresShell, sc);
 
       if (letterFrame) {
         // Initialize the first-letter-frame.  We don't want to use a text
         // content for a non-text frame (because we want its primary frame to
         // be a text frame).  So use its parent for the first-letter.
         nsIContent* letterContent = aTextContent->GetParent();
-        NS_ASSERTION(letterContent->GetBindingParent() != letterContent,
+        NS_ASSERTION(!letterContent->IsRootOfNativeAnonymousSubtree(),
                      "Reframes of this letter frame will mess with the root "
                      "of a native anonymous content subtree!");
         letterFrame->Init(letterContent, aParentFrame, nsnull);
 
         InitAndRestoreFrame(aState, aTextContent, letterFrame, nsnull,
                             textFrame);
 
         letterFrame->SetInitialChildList(nsnull, textFrame);
@@ -12942,17 +12944,17 @@ nsCSSFrameConstructor::RestyleForAppend(
 #ifdef DEBUG
   {
     for (PRInt32 index = aNewIndexInContainer;; ++index) {
       nsIContent *content = aContainer->GetChildAt(index);
       if (!content) {
         NS_ASSERTION(index != aNewIndexInContainer, "yikes, nothing appended");
         break;
       }
-      NS_ASSERTION(!content->IsNativeAnonymous(),
+      NS_ASSERTION(!content->IsRootOfNativeAnonymousSubtree(),
                    "native anonymous nodes should not be in child lists");
     }
   }
 #endif
   PRUint32 selectorFlags =
     aContainer->GetFlags() & (NODE_ALL_SELECTOR_FLAGS &
                               ~NODE_HAS_SLOW_SELECTOR_NOAPPEND);
   if (selectorFlags == 0)
@@ -13001,17 +13003,17 @@ nsCSSFrameConstructor::RestyleForAppend(
 // notification before the removal happened (and sometimes
 // CharacterDataChanged is more like a removal than an addition).
 // The comments are written and variables are named in terms of it being
 // a ContentInserted notification.
 void
 nsCSSFrameConstructor::RestyleForInsertOrChange(nsIContent* aContainer,
                                                 nsIContent* aChild)
 {
-  NS_ASSERTION(!aChild->IsNativeAnonymous(),
+  NS_ASSERTION(!aChild->IsRootOfNativeAnonymousSubtree(),
                "native anonymous nodes should not be in child lists");
   PRUint32 selectorFlags =
     aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
   if (selectorFlags == 0)
     return;
 
   if (selectorFlags & (NODE_HAS_SLOW_SELECTOR |
                        NODE_HAS_SLOW_SELECTOR_NOAPPEND)) {
@@ -13082,17 +13084,17 @@ nsCSSFrameConstructor::RestyleForInsertO
   }
 }
 
 void
 nsCSSFrameConstructor::RestyleForRemove(nsIContent* aContainer,
                                         nsIContent* aOldChild,
                                         PRInt32 aIndexInContainer)
 {
-  NS_ASSERTION(!aOldChild->IsNativeAnonymous(),
+  NS_ASSERTION(!aOldChild->IsRootOfNativeAnonymousSubtree(),
                "native anonymous nodes should not be in child lists");
   PRUint32 selectorFlags =
     aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
   if (selectorFlags == 0)
     return;
 
   if (selectorFlags & (NODE_HAS_SLOW_SELECTOR |
                        NODE_HAS_SLOW_SELECTOR_NOAPPEND)) {
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4630,17 +4630,17 @@ PresShell::CharacterDataChanged(nsIDocum
   }
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
   nsIContent *container = aContent->GetParent();
   PRUint32 selectorFlags =
     container ? (container->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
-  if (selectorFlags != 0 && !aContent->IsNativeAnonymous()) {
+  if (selectorFlags != 0 && !aContent->IsRootOfNativeAnonymousSubtree()) {
     PRUint32 index;
     if (aInfo->mAppend &&
         container->GetChildAt((index = container->GetChildCount() - 1)) ==
           aContent)
       mFrameConstructor->RestyleForAppend(container, index);
     else
       mFrameConstructor->RestyleForInsertOrChange(container, aContent);
   }
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -268,18 +268,20 @@ BRFrame::PeekOffsetWord(PRBool aForward,
 }
 
 #ifdef ACCESSIBILITY
 NS_IMETHODIMP BRFrame::GetAccessible(nsIAccessible** aAccessible)
 {
   NS_ENSURE_TRUE(mContent, NS_ERROR_FAILURE);
   nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
   NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIContent> parent = mContent->GetBindingParent();
-  if (parent && parent->IsNativeAnonymous() && parent->GetChildCount() == 1) {
+  nsIContent *parent = mContent->GetParent();
+  if (parent &&
+      parent->IsRootOfNativeAnonymousSubtree() &&
+      parent->GetChildCount() == 1) {
     // This <br> is the only node in a text control, therefore it is the hacky
     // "bogus node" used when there is no text in the control
     return NS_ERROR_FAILURE;
   }
   return accService->CreateHTMLBRAccessible(static_cast<nsIFrame*>(this), aAccessible);
 }
 #endif
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5712,17 +5712,17 @@ nsFrame::GetLastLeaf(nsPresContext* aPre
     if (!child)
       return;//nothing to do
     nsIFrame* siblingFrame;
     nsIContent* content;
     //ignore anonymous elements, e.g. mozTableAdd* mozTableRemove*
     //see bug 278197 comment #12 #13 for details
     while ((siblingFrame = child->GetNextSibling()) &&
            (content = siblingFrame->GetContent()) &&
-           !content->IsNativeAnonymous())
+           !content->IsRootOfNativeAnonymousSubtree())
       child = siblingFrame;
     *aFrame = child;
   }
 }
 
 void
 nsFrame::GetFirstLeaf(nsPresContext* aPresContext, nsIFrame **aFrame)
 {
@@ -5844,17 +5844,18 @@ nsIFrame::IsFocusable(PRInt32 *aTabIndex
           ui->mUserFocus != NS_STYLE_USER_FOCUS_NONE) {
         // Pass in default tabindex of -1 for nonfocusable and 0 for focusable
         tabIndex = 0;
       }
       isFocusable = mContent->IsFocusable(&tabIndex);
       if (!isFocusable && !aWithMouse &&
           GetType() == nsGkAtoms::scrollFrame &&
           mContent->IsNodeOfType(nsINode::eHTML) &&
-          !mContent->IsNativeAnonymous() && mContent->GetParent() &&
+          !mContent->IsRootOfNativeAnonymousSubtree() &&
+          mContent->GetParent() &&
           !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
         // Elements with scrollable view are focusable with script & tabbable
         // Otherwise you couldn't scroll them with keyboard, which is
         // an accessibility issue (e.g. Section 508 rules)
         // However, we don't make them to be focusable with the mouse,
         // because the extra focus outlines are considered unnecessarily ugly.
         // When clicked on, the selection position within the element 
         // will be enough to make them keyboard scrollable.
--- a/layout/inspector/src/inDOMView.cpp
+++ b/layout/inspector/src/inDOMView.cpp
@@ -344,17 +344,17 @@ inDOMView::GetRowProperties(PRInt32 inde
 NS_IMETHODIMP
 inDOMView::GetCellProperties(PRInt32 row, nsITreeColumn* col, nsISupportsArray *properties)
 {
   inDOMViewNode* node = nsnull;
   RowToNode(row, &node);
   if (!node) return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIContent> content = do_QueryInterface(node->node);
-  if (content && content->GetBindingParent()) {
+  if (content && content->IsInAnonymousSubtree()) {
     properties->AppendElement(kAnonymousAtom);
   }
 
   PRUint16 nodeType;
   node->node->GetNodeType(&nodeType);
   switch (nodeType) {
     case nsIDOMNode::ELEMENT_NODE:
       properties->AppendElement(kElementNodeAtom);