Commit 1194334a authored by bryner%brianryner.com's avatar bryner%brianryner.com
Browse files

Fix for crashes in document.addBinding():

- Don't allow the old binding to go away as we insert the new binding into the chain.
- When swapping the nsXBLInsertionPoint array for a content node, remove any entries from the old list that are also in the new list, so that we don't delete them.

Bug 296375, r+sr=bzbarsky.
parent 7e709162
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ public:
  PRInt32 GetInsertionPointCount() { return mElements->Count(); }

  nsXBLInsertionPoint* GetInsertionPointAt(PRInt32 i) { return NS_STATIC_CAST(nsXBLInsertionPoint*, mElements->ElementAt(i)); }
  void RemoveInsertionPointAt(PRInt32 i) { mElements->RemoveElementAt(i); }

private:
  nsVoidArray* mElements;
@@ -551,6 +552,31 @@ nsBindingManager::SetAnonymousNodesFor(nsIContent* aContent, nsVoidArray* aList)
  if (aList) {
    contentList = new nsAnonymousContentList(aList);
    if (!contentList) return NS_ERROR_OUT_OF_MEMORY;
  
    // If there are any items in aList that are already in aContent's
    // AnonymousNodesList, we need to make sure they don't get deleted as
    // the lists are swapped.  So, get the current list and check.
    // FIXME: This is O(n*m) where n and m are the insertion point list
    //        lengths.  But, there usually aren't many insertion points.

    if (mAnonymousNodesTable.ops) {
      nsAnonymousContentList *oldList =
        NS_STATIC_CAST(nsAnonymousContentList*,
                       LookupObject(mAnonymousNodesTable, aContent));
      if (oldList) {
        PRInt32 i = 0;
        while (i < oldList->GetInsertionPointCount()) {
          nsXBLInsertionPoint *point = oldList->GetInsertionPointAt(i);
          if (aList->IndexOf(point) != -1) {
            // We don't want this point to be deleted, so remove it
            // from the old list.
            oldList->RemoveInsertionPointAt(i);
          } else {
            ++i;
          }
        }
      }
    }
  }

  return SetOrRemoveObject(mAnonymousNodesTable, aContent, contentList);
+1 −1
Original line number Diff line number Diff line
@@ -613,8 +613,8 @@ nsXBLService::LoadBindings(nsIContent* aContent, nsIURI* aURL, PRBool aAugmentFl
    // XXX Handle adjusting the prototype chain! We need to somehow indicate to
    // InstallImplementation that the whole chain should just be whacked and rebuilt.
    // We are becoming the new binding.
    bindingManager->SetBinding(aContent, newBinding);
    baseBinding->SetBaseBinding(binding);
    bindingManager->SetBinding(aContent, newBinding);
  }
  else {
    // We loaded a style binding.  It goes on the end.