Commit 5b2088b9 authored by hyatt%netscape.com's avatar hyatt%netscape.com
Browse files

Fix for 94944. r=danm, sr=hewitt

parent 8960de08
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ public:
  NS_IMETHOD SetDefaultContent(nsIContent* aDefaultContent)=0;
  NS_IMETHOD GetDefaultContent(nsIContent** aDefaultContent)=0;

  NS_IMETHOD SetDefaultContentTemplate(nsIContent* aDefaultContent)=0;
  NS_IMETHOD GetDefaultContentTemplate(nsIContent** aDefaultContent)=0;

  NS_IMETHOD AddChild(nsIContent* aChildElement)=0;
  NS_IMETHOD InsertChildAt(PRInt32 aIndex, nsIContent* aChildElement)=0;
  NS_IMETHOD RemoveChild(nsIContent* aChildElement)=0;
+3 −3
Original line number Diff line number Diff line
@@ -600,7 +600,7 @@ PRBool PR_CALLBACK RealizeDefaultContent(nsHashKey* aKey, void* aData, void* aCl
    
    if (insCount == 0) {
      nsCOMPtr<nsIContent> defContent;
      currPoint->GetDefaultContent(getter_AddRefs(defContent));
      currPoint->GetDefaultContentTemplate(getter_AddRefs(defContent));
      if (defContent) {
        // We need to take this template and use it to realize the
        // actual default content (through cloning).
@@ -743,8 +743,6 @@ nsXBLBinding::GenerateAnonymousContent()
      clonedContent = do_QueryInterface(clonedNode);
      SetAnonymousContent(clonedContent);

      mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);

      if (hasInsertionPoints) {
        // Now check and see if we have a single insertion point 
        // or multiple insertion points.
@@ -847,6 +845,8 @@ nsXBLBinding::GenerateAnonymousContent()
        mInsertionPointTable->Enumerate(RealizeDefaultContent, &data);
      }
    }

    mPrototypeBinding->SetInitialAttributes(mBoundElement, mContent);
  }

  // Always check the content element for potential attributes.
+17 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ nsXBLInsertionPoint::nsXBLInsertionPoint(nsIContent* aParentElement, PRUint32 aI
  NS_INIT_REFCNT();
  mParentElement = aParentElement;
  mIndex = aIndex;
  mDefaultContent = aDefaultContent;
  mDefaultContentTemplate = aDefaultContent;
}

nsXBLInsertionPoint::~nsXBLInsertionPoint()
@@ -71,6 +71,22 @@ nsXBLInsertionPoint::GetDefaultContent(nsIContent** aDefaultContent)
  return NS_OK;
}

NS_IMETHODIMP
nsXBLInsertionPoint::SetDefaultContentTemplate(nsIContent* aDefaultContent)
{
  mDefaultContentTemplate = aDefaultContent;
  return NS_OK;
}

NS_IMETHODIMP
nsXBLInsertionPoint::GetDefaultContentTemplate(nsIContent** aDefaultContent)
{
  *aDefaultContent = mDefaultContentTemplate;
  NS_IF_ADDREF(*aDefaultContent);
  return NS_OK;
}


NS_IMETHODIMP
nsXBLInsertionPoint::AddChild(nsIContent* aChildElement)
{
+6 −1
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@ public:
  NS_IMETHOD SetDefaultContent(nsIContent* aDefaultContent);
  NS_IMETHOD GetDefaultContent(nsIContent** aDefaultContent);

  NS_IMETHOD SetDefaultContentTemplate(nsIContent* aDefaultContent);
  NS_IMETHOD GetDefaultContentTemplate(nsIContent** aDefaultContent);

  NS_IMETHOD AddChild(nsIContent* aChildElement);
  NS_IMETHOD InsertChildAt(PRInt32 aIndex, nsIContent* aChildElement);
  NS_IMETHOD RemoveChild(nsIContent* aChildElement);
@@ -57,7 +60,9 @@ protected:
  nsIContent* mParentElement;            // This ref is weak.  The parent of the <children> element.
  PRInt32 mIndex;                        // The index of this insertion point. -1 is a pseudo-point.
  nsCOMPtr<nsISupportsArray> mElements;  // An array of elements present at the insertion point.
  nsCOMPtr<nsIContent> mDefaultContent;           // The default content at this insertion point.
  nsCOMPtr<nsIContent> mDefaultContentTemplate ;           // The template default content that will be cloned if
                                                           // the insertion point is empty.
  nsCOMPtr<nsIContent> mDefaultContent;  // The cloned default content obtained by cloning mDefaultContentTemplate.
};

extern nsresult
+86 −15
Original line number Diff line number Diff line
@@ -641,7 +641,7 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI
    xblAttr->GetElement(getter_AddRefs(element));

    nsCOMPtr<nsIContent> realElement;
    LocateInstance(content, aAnonymousContent, element, getter_AddRefs(realElement));
    LocateInstance(aChangedElement, content, aAnonymousContent, element, getter_AddRefs(realElement));

    xblAttr->GetDstAttribute(getter_AddRefs(dstAttr));

@@ -737,7 +737,7 @@ PRBool PR_CALLBACK InstantiateInsertionPoint(nsHashKey* aKey, void* aData, void*
  binding->GetAnonymousContent(getter_AddRefs(instanceRoot));
  nsCOMPtr<nsIContent> templRoot;
  proto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(templRoot));
  proto->LocateInstance(templRoot, instanceRoot, content, getter_AddRefs(realContent));
  proto->LocateInstance(nsnull, templRoot, instanceRoot, content, getter_AddRefs(realContent));
  if (!realContent)
    binding->GetBoundElement(getter_AddRefs(realContent));

@@ -806,7 +806,7 @@ nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent*
      entry->GetDefaultContent(aDefaultContent); // Addref happens here.
      nsCOMPtr<nsIContent> templContent;
      GetImmediateChild(kContentAtom, getter_AddRefs(templContent));
      LocateInstance(templContent, aCopyRoot, content, getter_AddRefs(realContent));
      LocateInstance(nsnull, templContent, aCopyRoot, content, getter_AddRefs(realContent));
    }
    else {
      // We got nothin'.  Bail.
@@ -844,7 +844,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement,
        entry->GetDefaultContent(aDefaultContent); // Addref happens here.
        nsCOMPtr<nsIContent> templContent;
        GetImmediateChild(kContentAtom, getter_AddRefs(templContent));
        LocateInstance(templContent, aCopyRoot, content, getter_AddRefs(realContent));
        LocateInstance(nsnull, templContent, aCopyRoot, content, getter_AddRefs(realContent));
      }
      else {
        // The only insertion point specified was actually a filtered insertion point.
@@ -964,30 +964,94 @@ nsXBLPrototypeBinding::ConstructHandlers()
}

void
nsXBLPrototypeBinding::LocateInstance(nsIContent* aTemplRoot, nsIContent* aCopyRoot, 
nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, nsIContent* aTemplRoot, nsIContent* aCopyRoot, 
                                      nsIContent* aTemplChild, nsIContent** aCopyResult)
{
  // XXX We will get in trouble if the binding instantiation deviates from the template
  // in the prototype.
  if (aTemplChild == aTemplRoot) {
  if (aTemplChild == aTemplRoot || !aTemplChild) {
    *aCopyResult = nsnull;
    return;
  }

  nsCOMPtr<nsIContent> templParent;
  nsCOMPtr<nsIContent> copyParent;

  nsCOMPtr<nsIContent> childPoint;
  aTemplChild->GetParent(*getter_AddRefs(templParent));
  
  if (aBoundElement) {
    nsCOMPtr<nsIAtom> tag;
    templParent->GetTag(*getter_AddRefs(tag));
    if (tag == kChildrenAtom) {
      childPoint = templParent;
      childPoint->GetParent(*getter_AddRefs(templParent));
    }
  }

  if (!templParent)
    return;

  if (templParent.get() == aTemplRoot)
    copyParent = aCopyRoot;
  else
    LocateInstance(aTemplRoot, aCopyRoot, templParent, getter_AddRefs(copyParent));
    LocateInstance(aBoundElement, aTemplRoot, aCopyRoot, templParent, getter_AddRefs(copyParent));
  
  if (childPoint && aBoundElement) {
    // First we have to locate this insertion point and use its index and its
    // count to detemine our precise position within the template.
    nsCOMPtr<nsIDocument> doc;
    aBoundElement->GetDocument(*getter_AddRefs(doc));
    nsCOMPtr<nsIBindingManager> bm;
    doc->GetBindingManager(getter_AddRefs(bm));
    nsCOMPtr<nsIXBLBinding> binding;
    bm->GetBinding(aBoundElement, getter_AddRefs(binding));
    
    nsCOMPtr<nsIXBLBinding> currBinding = binding;
    while (currBinding) {
      nsCOMPtr<nsIContent> anonContent;
      currBinding->GetAnonymousContent(getter_AddRefs(anonContent));
      if (anonContent)
        break;
      nsCOMPtr<nsIXBLBinding> tempBinding = currBinding;
      tempBinding->GetBaseBinding(getter_AddRefs(currBinding));
    }

    nsCOMPtr<nsISupportsArray> points;
    currBinding->GetInsertionPointsFor(copyParent, getter_AddRefs(points));
    nsCOMPtr<nsIXBLInsertionPoint> insertionPoint;
    PRUint32 count;
    points->Count(&count);
    for (PRUint32 i = 0; i < count; i++) {
      // Next we have to find the real insertion point for this proto insertion
      // point.  If it does not contain any default content, then we should 
      // return null, since the content is not in the clone.
      nsCOMPtr<nsIXBLInsertionPoint> currPoint = getter_AddRefs((nsIXBLInsertionPoint*)points->ElementAt(i));
      nsCOMPtr<nsIContent> defContent;
      currPoint->GetDefaultContentTemplate(getter_AddRefs(defContent));
      if (defContent == childPoint) {
        // Now check to see if we even built default content at this
        // insertion point.
        currPoint->GetDefaultContent(getter_AddRefs(defContent));
        if (defContent) {
          // Find out the index of the template element within the <children> elt.
          PRInt32 index;
          childPoint->IndexOf(aTemplChild, index);
          
          // Now we just have to find the corresponding elt underneath the cloned
          // default content.
          defContent->ChildAt(index, *aCopyResult);
        } 
        break;
      }
    }
  }
  else if (copyParent)
  {
    PRInt32 index;
    templParent->IndexOf(aTemplChild, index);
    copyParent->ChildAt(index, *aCopyResult); // Addref happens here.
  }
}

struct nsXBLAttrChangeData
{
@@ -1039,7 +1103,8 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure)
      curr->GetElement(getter_AddRefs(element));

      nsCOMPtr<nsIContent> realElement;
      changeData->mProto->LocateInstance(content, changeData->mContent, element, getter_AddRefs(realElement));
      changeData->mProto->LocateInstance(changeData->mBoundElement,
                                         content, changeData->mContent, element, getter_AddRefs(realElement));
      if (realElement) {
        realElement->SetAttribute(kNameSpaceID_None, dst, value, PR_FALSE);
        nsCOMPtr<nsIAtom> tag;
@@ -1240,7 +1305,7 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
          nsISupportsKey key(atom);
          mInsertionPointTable->Put(&key, xblIns);
          
          token = nsCRT::strtok( newStr, ", ", &newStr );
          token = nsCRT::strtok( newStr, "| ", &newStr );
        }

        nsMemory::Free(str);
@@ -1267,8 +1332,14 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
      // in situations where no content ends up being placed at the insertion point.
      PRInt32 defaultCount;
      child->ChildCount(defaultCount);
      if (defaultCount > 0)
      if (defaultCount > 0) {
        // Annotate the insertion point with our default content.
        xblIns->SetDefaultContent(child);

        // Reconnect back to our parent for access later.  This makes "inherits" easier
        // to work with on default content.
        child->SetParent(parent);
      }
    }
  }
}
Loading