Bug 90983: Remove the nsFragmentObserver and always notify when inserting from fragments so as to not regress mutation events with my next patch. r/sr=bz

This commit is contained in:
cvshook@sicking.cc
2006-06-02 00:26:42 +00:00
parent 0c6a7ae735
commit c524ac0901

View File

@@ -2597,91 +2597,6 @@ PRBool IsAllowedAsChild(nsIContent* aNewChild, PRUint16 aNewNodeType,
return PR_FALSE;
}
class nsFragmentObserver : public nsStubDocumentObserver {
public:
NS_DECL_ISUPPORTS
nsFragmentObserver(PRUint32 aOldChildCount, nsIContent* aParent,
nsIDocument* aDocument) :
mOldChildCount(aOldChildCount),
mChildrenBound(0),
mParent(aParent),
mDocument(aDocument)
{
NS_ASSERTION(mParent, "Must have parent!");
}
virtual void BeginUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType) {
// Make sure to notify on whatever content has been appended thus far
Notify();
}
virtual void DocumentWillBeDestroyed(nsIDocument *aDocument) {
Disconnect();
}
void Connect() {
if (mDocument) {
mDocument->AddObserver(this);
}
}
void Disconnect() {
if (mDocument) {
mDocument->RemoveObserver(this);
}
mDocument = nsnull;
}
void Finish() {
// Notify on any remaining content
Notify();
Disconnect();
}
void Notify() {
if (mDocument && mDocument == mParent->GetCurrentDoc()) {
if (mChildrenBound > 0) {
// Some stuff got bound since we notified last time. Notify on it.
PRUint32 boundCount = mOldChildCount + mChildrenBound;
PRUint32 notifySlot = mOldChildCount;
// Make sure to update mChildrenBound and mOldChildCount so that if
// ContentAppended calls BeginUpdate for some reason (eg XBL) so we
// reenter Notify() we won't double-notify.
mChildrenBound = 0;
mOldChildCount = boundCount;
if (boundCount == mParent->GetChildCount()) {
// All the kids have been bound already. Just append
mDocument->ContentAppended(mParent, notifySlot);
} else {
// Just notify on the already-bound kids
for (PRUint32 i = notifySlot; i < boundCount; ++i) {
nsIContent* child = mParent->GetChildAt(i);
// Could have no child if script has rearranged the DOM or
// something...
if (child) {
mDocument->ContentInserted(mParent, child, i);
}
}
}
}
}
}
void ChildBound() {
++mChildrenBound;
}
private:
PRUint32 mOldChildCount;
PRUint32 mChildrenBound; // Number of children bound since we last notified
nsCOMPtr<nsIContent> mParent;
nsIDocument* mDocument;
};
NS_IMPL_ISUPPORTS1(nsFragmentObserver, nsIDocumentObserver)
/* static */
nsresult
nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
@@ -2806,7 +2721,6 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
*/
if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
PRUint32 count = newContent->GetChildCount();
PRBool do_notify = refContent || !aParent;
// Copy the children into a separate array to avoid having to deal with
// mutations to the fragment while we're inserting.
@@ -2833,21 +2747,6 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
mutated = mutated || guard.Mutated(1);
}
// Set up observer that notifies if needed.
nsRefPtr<nsFragmentObserver> fragmentObs;
if (count && !do_notify) {
fragmentObs = new nsFragmentObserver(container->GetChildCount(), aParent, aDocument);
NS_ENSURE_TRUE(fragmentObs, NS_ERROR_OUT_OF_MEMORY);
fragmentObs->Connect();
}
// If do_notify is true, then we don't have to handle the notifications
// ourselves... Also, if count is 0 there will be no updates. So we only
// want an update batch to happen if count is nonzero and do_notify is not
// true.
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL,
count && !do_notify);
// Iterate through the fragment's children, and insert them in the new
// parent
for (i = 0; i < count; ++i) {
@@ -2865,8 +2764,7 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
if (insPos < 0) {
// Someone seriously messed up the childlist. We have no idea
// where to insert the remaining children, so just bail.
res = NS_ERROR_DOM_NOT_FOUND_ERR;
break;
return NS_ERROR_DOM_NOT_FOUND_ERR;
}
nsCOMPtr<nsIDOMNode> tmpNode = do_QueryInterface(childContent);
@@ -2876,8 +2774,7 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
if (childContent->GetNodeParent() ||
!IsAllowedAsChild(childContent, tmpType, aParent, aDocument, PR_FALSE,
refContent)) {
res = NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
break;
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
}
@@ -2885,14 +2782,8 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
// XXXbz how come no reparenting here? That seems odd...
// Insert the child.
res = container->InsertChildAt(childContent, insPos, do_notify);
if (NS_FAILED(res)) {
break;
}
if (fragmentObs) {
fragmentObs->ChildBound();
}
res = container->InsertChildAt(childContent, insPos, PR_TRUE);
NS_ENSURE_SUCCESS(res, res);
// Check to see if any evil mutation events mucked around with the
// child list.
@@ -2900,22 +2791,6 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace,
++insPos;
}
if (NS_FAILED(res)) {
if (fragmentObs) {
fragmentObs->Disconnect();
}
// We could try to put the nodes back into the fragment here if we
// really cared.
return res;
}
if (fragmentObs) {
NS_ASSERTION(count && !do_notify, "Unexpected state");
fragmentObs->Finish();
}
}
else {
// Not inserting a fragment but rather a single node.