Bug 502937. Part 2.5. Provide an API to get the flattened tree parent of an nsIContent. r=bzbarsky
authorTimothy Nikkel <tnikkel@gmail.com>
Fri, 16 Apr 2010 13:15:28 -0500
changeset 40937 aa6171e5b8e72fae8c50b28c0a50f5108149a750
parent 40936 e6ba6ff5084165a9169d4867db26289229953bd2
child 40938 f80de1a7c60466ef95cb33152d4d6d0a4df72905
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs502937
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Bug 502937. Part 2.5. Provide an API to get the flattened tree parent of an nsIContent. r=bzbarsky
content/base/public/nsIContent.h
content/base/src/nsGenericElement.cpp
content/xbl/src/nsBindingManager.cpp
content/xbl/src/nsBindingManager.h
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLBinding.h
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xbl/src/nsXBLPrototypeBinding.h
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -66,18 +66,18 @@ enum nsLinkState {
   eLinkState_Unknown    = 0,
   eLinkState_Unvisited  = 1,
   eLinkState_Visited    = 2,
   eLinkState_NotLink    = 3
 };
 
 // IID for the nsIContent interface
 #define NS_ICONTENT_IID       \
-{ 0x07734640, 0x0900, 0x480d, \
- { 0x97, 0x5a, 0x31, 0xc7, 0x0e, 0xcd, 0x15, 0x2b } }
+{ 0x9d15dea4, 0xa112, 0x40f4, \
+ { 0xbd, 0xa9, 0x23, 0xc0, 0xed, 0xde, 0x08, 0x9c } }
 
 /**
  * A node of content in a document's content model. This interface
  * is supported by all content objects.
  */
 class nsIContent : public nsINode {
 public:
 #ifdef MOZILLA_INTERNAL_API
@@ -638,16 +638,24 @@ public:
    * 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;
 
   /**
+   * Returns the content node that is the parent of this node in the flattened
+   * tree.
+   *
+   * @return the flattened tree parent
+   */
+  nsIContent *GetFlattenedTreeParent() const;
+
+  /**
    * Get the base URI for any relative URIs within this piece of
    * content. Generally, this is the document's base URI, but certain
    * content carries a local base for backward compatibility, and XML
    * supports setting a per-node base URI.
    *
    * @return the base URI
    */
   virtual already_AddRefed<nsIURI> GetBaseURI() const = 0;
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -626,16 +626,33 @@ nsIContent::FindFirstNonNativeAnonymous(
       // Oops, this function signature allows casting const to
       // non-const.  (Then again, so does GetChildAt(0)->GetParent().)
       return const_cast<nsIContent*>(content);
     }
   }
   return nsnull;
 }
 
+nsIContent*
+nsIContent::GetFlattenedTreeParent() const
+{
+  nsIContent *parent = GetParent();
+  if (parent && parent->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
+    nsIDocument *doc = parent->GetOwnerDoc();
+    if (doc) {
+      nsIContent* insertionElement =
+        doc->BindingManager()->GetNestedInsertionPoint(parent, this);
+      if (insertionElement) {
+        parent = insertionElement;
+      }
+    }
+  }
+  return parent;
+}
+
 //----------------------------------------------------------------------
 
 NS_IMPL_ADDREF(nsChildContentList)
 NS_IMPL_RELEASE(nsChildContentList)
 
 NS_INTERFACE_TABLE_HEAD(nsChildContentList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsChildContentList)
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -821,17 +821,18 @@ nsBindingManager::GetXBLChildNodesFor(ns
 nsINodeList*
 nsBindingManager::GetXBLChildNodesFor(nsIContent* aContent)
 {
   PRBool dummy;
   return GetXBLChildNodesInternal(aContent, &dummy);
 }
 
 nsIContent*
-nsBindingManager::GetInsertionPoint(nsIContent* aParent, nsIContent* aChild,
+nsBindingManager::GetInsertionPoint(nsIContent* aParent,
+                                    const nsIContent* aChild,
                                     PRUint32* aIndex)
 {
   nsXBLBinding *binding = GetBinding(aParent);
   return binding ? binding->GetInsertionPoint(aChild, aIndex) : nsnull;
 }
 
 nsIContent*
 nsBindingManager::GetSingleInsertionPoint(nsIContent* aParent,
@@ -1397,17 +1398,18 @@ nsBindingManager::MediumFeaturesChanged(
     return NS_OK;
 
   MediumFeaturesChangedData data = { aPresContext, aRulesChanged };
   set.EnumerateEntries(EnumMediumFeaturesChanged, &data);
   return NS_OK;
 }
 
 nsIContent*
-nsBindingManager::GetNestedInsertionPoint(nsIContent* aParent, nsIContent* aChild)
+nsBindingManager::GetNestedInsertionPoint(nsIContent* aParent,
+                                          const nsIContent* aChild)
 {
   // Check to see if the content is anonymous.
   if (aChild->GetBindingParent() == aParent)
     return nsnull; // It is anonymous. Don't use the insertion point, since that's only
                    // for the explicit kids.
 
   PRUint32 index;
   nsIContent *insertionElement = GetInsertionPoint(aParent, aChild, &index);
--- a/content/xbl/src/nsBindingManager.h
+++ b/content/xbl/src/nsBindingManager.h
@@ -162,26 +162,31 @@ public:
    */
   // XXXbz That's false.  The aIndex doesn't seem to accurately reflect
   // anything resembling reality in terms of inserting content.  It's really
   // only used to tell apart two different insertion points with the same
   // insertion parent when managing our internal data structures.  We really
   // shouldn't be handing it out in our public API, since it's not useful to
   // anyone.
   nsIContent* GetInsertionPoint(nsIContent* aParent,
-                                nsIContent* aChild, PRUint32* aIndex);
+                                const nsIContent* aChild, PRUint32* aIndex);
 
   /**
    * Return the unfiltered insertion point for the specified parent
    * element. If other filtered insertion points exist,
    * aMultipleInsertionPoints will be set to true.
    */
   nsIContent* GetSingleInsertionPoint(nsIContent* aParent, PRUint32* aIndex,
                                       PRBool* aMultipleInsertionPoints);
 
+  nsIContent* GetNestedInsertionPoint(nsIContent* aParent,
+                                      const nsIContent* aChild);
+  nsIContent* GetNestedSingleInsertionPoint(nsIContent* aParent,
+                                            PRBool* aMultipleInsertionPoints);
+
   nsresult AddLayeredBinding(nsIContent* aContent, nsIURI* aURL,
                              nsIPrincipal* aOriginPrincipal);
   nsresult RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL);
   nsresult LoadBindingDocument(nsIDocument* aBoundDoc, nsIURI* aURL,
                                nsIPrincipal* aOriginPrincipal);
 
   nsresult AddToAttachedQueue(nsXBLBinding* aBinding);
   void ProcessAttachedQueue(PRUint32 aSkipSize = 0);
@@ -232,20 +237,16 @@ protected:
   nsIXPConnectWrappedJS* GetWrappedJS(nsIContent* aContent);
   nsresult SetWrappedJS(nsIContent* aContent, nsIXPConnectWrappedJS* aResult);
 
   nsINodeList* GetXBLChildNodesInternal(nsIContent* aContent,
                                         PRBool* aIsAnonymousContentList);
   nsINodeList* GetAnonymousNodesInternal(nsIContent* aContent,
                                          PRBool* aIsAnonymousContentList);
 
-  nsIContent* GetNestedInsertionPoint(nsIContent* aParent, nsIContent* aChild);
-  nsIContent* GetNestedSingleInsertionPoint(nsIContent* aParent,
-                                            PRBool* aMultipleInsertionPoints);
-
   // Called by ContentAppended and ContentInserted to handle a single child
   // insertion.  aChild must not be null.  aContainer may be null.
   // aIndexInContainer is the index of the child in the parent.  aAppend is
   // true if this child is being appended, not inserted.
   void HandleChildInsertion(nsIContent* aContainer, nsIContent* aChild,
                             PRUint32 aIndexInContainer, PRBool aAppend);
 
   // For the given container under which a child is being added, given
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -1495,17 +1495,17 @@ nsXBLBinding::GetExistingInsertionPoints
   }
 
   nsInsertionPointList* result = nsnull;
   mInsertionPointTable->Get(aParent, &result);
   return result;
 }
 
 nsIContent*
-nsXBLBinding::GetInsertionPoint(nsIContent* aChild, PRUint32* aIndex)
+nsXBLBinding::GetInsertionPoint(const nsIContent* aChild, PRUint32* aIndex)
 {
   if (mContent) {
     return mPrototypeBinding->GetInsertionPoint(mBoundElement, mContent,
                                                 aChild, aIndex);
   }
 
   if (mNextBinding)
     return mNextBinding->GetInsertionPoint(aChild, aIndex);
--- a/content/xbl/src/nsXBLBinding.h
+++ b/content/xbl/src/nsXBLBinding.h
@@ -124,17 +124,17 @@ public:
   // is owned by the binding, you should not delete it.
   nsresult GetInsertionPointsFor(nsIContent* aParent,
                                  nsInsertionPointList** aResult);
 
   nsInsertionPointList* GetExistingInsertionPointsFor(nsIContent* aParent);
 
   // XXXbz this aIndex has nothing to do with an index into the child
   // list of the insertion parent or anything.
-  nsIContent* GetInsertionPoint(nsIContent* aChild, PRUint32* aIndex);
+  nsIContent* GetInsertionPoint(const nsIContent* aChild, PRUint32* aIndex);
 
   nsIContent* GetSingleInsertionPoint(PRUint32* aIndex,
                                       PRBool* aMultipleInsertionPoints);
 
   void AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceID,
                         PRBool aRemoveFlag, PRBool aNotify);
 
   void ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument);
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -706,17 +706,17 @@ nsXBLPrototypeBinding::InstantiateInsert
   InsertionData data(aBinding, this);
   if (mInsertionPointTable)
     mInsertionPointTable->Enumerate(InstantiateInsertionPoint, &data);
 }
 
 nsIContent*
 nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement,
                                          nsIContent* aCopyRoot,
-                                         nsIContent* aChild,
+                                         const nsIContent* aChild,
                                          PRUint32* aIndex)
 {
   if (!mInsertionPointTable)
     return nsnull;
 
   nsISupportsKey key(aChild->Tag());
   nsXBLInsertionPointEntry* entry = static_cast<nsXBLInsertionPointEntry*>(mInsertionPointTable->Get(&key));
   if (!entry) {
--- a/content/xbl/src/nsXBLPrototypeBinding.h
+++ b/content/xbl/src/nsXBLPrototypeBinding.h
@@ -159,17 +159,18 @@ public:
 
   nsresult FlushSkinSheets();
 
   void InstantiateInsertionPoints(nsXBLBinding* aBinding);
 
   // XXXbz this aIndex has nothing to do with an index into the child
   // list of the insertion parent or anything.
   nsIContent* GetInsertionPoint(nsIContent* aBoundElement,
-                                nsIContent* aCopyRoot, nsIContent *aChild,
+                                nsIContent* aCopyRoot,
+                                const nsIContent *aChild,
                                 PRUint32* aIndex);
 
   nsIContent* GetSingleInsertionPoint(nsIContent* aBoundElement,
                                       nsIContent* aCopyRoot,
                                       PRUint32* aIndex, PRBool* aMultiple);
 
   nsIAtom* GetBaseTag(PRInt32* aNamespaceID);
   void SetBaseTag(PRInt32 aNamespaceID, nsIAtom* aTag);