diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 4b24c797ce50..8a43a528eeeb 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -44,6 +44,7 @@ #include "nsChangeHint.h" #include "nsCOMArray.h" #include "nsIDocumentObserver.h" +#include "nsCOMPtr.h" class nsIAtom; class nsIContent; @@ -384,6 +385,7 @@ public: // Observation hooks used to propagate notifications to document observers. // BeginUpdate must be called before any batch of modifications of the // content model or of style data, EndUpdate must be called afterward. + // To make this easy and painless, use the mozAutoDocUpdate helper class. NS_IMETHOD BeginUpdate(nsUpdateType aUpdateType) = 0; NS_IMETHOD EndUpdate(nsUpdateType aUpdateType) = 0; NS_IMETHOD BeginLoad() = 0; @@ -475,6 +477,38 @@ public: }; +/** + * Helper class to automatically handle batching of document updates. This + * class will call BeginUpdate on construction and EndUpdate on destruction on + * the given document with the given update type. The document could be null, + * in which case no updates will be called. The constructor also takes a + * boolean that can be set to false to prevent notifications. + */ +class mozAutoDocUpdate +{ +public: + mozAutoDocUpdate(nsIDocument* aDocument, nsUpdateType aUpdateType, + PRBool aNotify) : + mDocument(aNotify ? aDocument : nsnull), + mUpdateType(aUpdateType) + { + if (mDocument) { + mDocument->BeginUpdate(mUpdateType); + } + } + + ~mozAutoDocUpdate() + { + if (mDocument) { + mDocument->EndUpdate(mUpdateType); + } + } + +private: + nsCOMPtr mDocument; + nsUpdateType mUpdateType; +}; + // XXX These belong somewhere else nsresult NS_NewHTMLDocument(nsIDocument** aInstancePtrResult); diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index 634b4c70d3b5..df823fcecd5b 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -1175,9 +1175,7 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer, return NS_ERROR_NULL_POINTER; } - if (aNotify && mDocument) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); mText.SetTo(aBuffer, aLength); @@ -1202,7 +1200,6 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer, // Trigger a reflow if (aNotify && mDocument) { mDocument->ContentChanged(this, nsnull); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } return NS_OK; } @@ -1219,9 +1216,7 @@ nsGenericDOMDataNode::SetText(const char* aBuffer, PRInt32 aLength, return NS_ERROR_NULL_POINTER; } - if (aNotify && mDocument) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); mText.SetTo(aBuffer, aLength); @@ -1244,7 +1239,6 @@ nsGenericDOMDataNode::SetText(const char* aBuffer, PRInt32 aLength, // Trigger a reflow if (aNotify && mDocument) { mDocument->ContentChanged(this, nsnull); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } return NS_OK; @@ -1254,9 +1248,7 @@ NS_IMETHODIMP nsGenericDOMDataNode::SetText(const nsAString& aStr, PRBool aNotify) { - if (aNotify && mDocument) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); mText = aStr; @@ -1281,7 +1273,6 @@ nsGenericDOMDataNode::SetText(const nsAString& aStr, // Trigger a reflow if (aNotify && mDocument) { mDocument->ContentChanged(this, nsnull); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } return NS_OK; diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index f82cb88b712e..ef08730f3a0f 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2614,9 +2614,12 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, PRBool do_notify = !!aRefChild; - if (count && !do_notify && mDocument) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - } + // 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(mDocument, UPDATE_CONTENT_MODEL, + count && !do_notify); /* * Iterate through the fragments children, removing each from @@ -2654,7 +2657,6 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, if (count && !do_notify && mDocument) { mDocument->ContentAppended(this, old_count); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } doc_fragment->DropChildReferences(); @@ -3403,9 +3405,9 @@ nsGenericContainerElement::SetAttr(nsINodeInfo* aNodeInfo, } // Begin the update _before_ changing the attr value + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + if (aNotify && mDocument) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - mDocument->AttributeWillChange(this, nameSpaceID, name); } @@ -3467,7 +3469,6 @@ nsGenericContainerElement::SetAttr(nsINodeInfo* aNodeInfo, PRInt32 modHint = modification ? PRInt32(nsIDOMMutationEvent::MODIFICATION) : PRInt32(nsIDOMMutationEvent::ADDITION); mDocument->AttributeChanged(this, nameSpaceID, name, modHint); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } @@ -3563,54 +3564,57 @@ nsGenericContainerElement::UnsetAttr(PRInt32 aNameSpaceID, return NS_ERROR_NULL_POINTER; } - nsresult rv = NS_OK; - if (nsnull != mAttributes) { PRInt32 count = mAttributes->Count(); PRInt32 index; PRBool found = PR_FALSE; + nsGenericAttribute* attr = nsnull; for (index = 0; index < count; index++) { - nsGenericAttribute* attr = (nsGenericAttribute*)mAttributes->ElementAt(index); + attr = (nsGenericAttribute*)mAttributes->ElementAt(index); if ((aNameSpaceID == kNameSpaceID_Unknown || attr->mNodeInfo->NamespaceEquals(aNameSpaceID)) && attr->mNodeInfo->Equals(aName)) { - if (aNotify && (nsnull != mDocument)) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - - mDocument->AttributeWillChange(this, aNameSpaceID, aName); - } - - if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { - nsCOMPtr node(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_ATTRMODIFIED; - mutation.mTarget = node; - - nsAutoString attrName; - aName->ToString(attrName); - nsCOMPtr attrNode; - GetAttributeNode(attrName, getter_AddRefs(attrNode)); - mutation.mRelatedNode = attrNode; - - mutation.mAttrName = aName; - if (!attr->mValue.IsEmpty()) - mutation.mPrevAttrValue = do_GetAtom(attr->mValue); - mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL; - - nsEventStatus status = nsEventStatus_eIgnore; - this->HandleDOMEvent(nsnull, &mutation, nsnull, - NS_EVENT_FLAG_INIT, &status); - } - - mAttributes->RemoveElementAt(index); - delete attr; found = PR_TRUE; break; } } - if (NS_SUCCEEDED(rv) && found && mDocument) { + if (!found) { + return NS_OK; + } + + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + if (aNotify && mDocument) { + mDocument->AttributeWillChange(this, aNameSpaceID, aName); + } + + if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { + nsCOMPtr node(do_QueryInterface(NS_STATIC_CAST(nsIContent *, this))); + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_ATTRMODIFIED; + mutation.mTarget = node; + + nsAutoString attrName; + aName->ToString(attrName); + nsCOMPtr attrNode; + GetAttributeNode(attrName, getter_AddRefs(attrNode)); + mutation.mRelatedNode = attrNode; + + mutation.mAttrName = aName; + if (!attr->mValue.IsEmpty()) + mutation.mPrevAttrValue = do_GetAtom(attr->mValue); + mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL; + + nsEventStatus status = nsEventStatus_eIgnore; + this->HandleDOMEvent(nsnull, &mutation, nsnull, + NS_EVENT_FLAG_INIT, &status); + } + + mAttributes->RemoveElementAt(index); + delete attr; + + if (mDocument) { nsCOMPtr bindingManager; mDocument->GetBindingManager(getter_AddRefs(bindingManager)); nsCOMPtr binding; @@ -3621,12 +3625,11 @@ nsGenericContainerElement::UnsetAttr(PRInt32 aNameSpaceID, if (aNotify) { mDocument->AttributeChanged(this, aNameSpaceID, aName, nsIDOMMutationEvent::REMOVAL); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } } - return rv; + return NS_OK; } nsresult @@ -3820,9 +3823,8 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid, { NS_PRECONDITION(nsnull != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/ if (rv) { NS_ADDREF(aKid); @@ -3850,9 +3852,7 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid, } } } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } + return NS_OK; } @@ -3864,9 +3864,8 @@ nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid, { NS_PRECONDITION(nsnull != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != mDocument)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); nsRange::OwnerChildReplaced(this, aIndex, oldKid); PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex); @@ -3883,9 +3882,7 @@ nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid, oldKid->SetParent(nsnull); NS_RELEASE(oldKid); } - if (aNotify && (nsnull != mDocument)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } + return NS_OK; } @@ -3895,9 +3892,8 @@ nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, { NS_PRECONDITION(nsnull != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + PRBool rv = mChildren.AppendElement(aKid); if (rv) { NS_ADDREF(aKid); @@ -3925,9 +3921,7 @@ nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, } } } - if (aNotify && doc) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } + return NS_OK; } @@ -3937,9 +3931,7 @@ nsGenericContainerElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); if (oldKid) { nsIDocument* doc = mDocument; - if (aNotify && doc) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { nsCOMPtr node(do_QueryInterface(oldKid)); @@ -3968,9 +3960,6 @@ nsGenericContainerElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE); oldKid->SetParent(nsnull); NS_RELEASE(oldKid); - if (aNotify && doc) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } } return NS_OK; diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 527956b255ac..5811d69f0d66 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1676,45 +1676,43 @@ nsGenericHTMLElement::SetAttr(PRInt32 aNameSpaceID, // string value was mapped to nsHTMLValue, set it that way return SetHTMLAttribute(aAttribute, val, aNotify); } - else { - if (ParseCommonAttribute(aAttribute, aValue, val)) { - // string value was mapped to nsHTMLValue, set it that way - return SetHTMLAttribute(aAttribute, val, aNotify); - } - if (aValue.IsEmpty()) { // if empty string - val.SetEmptyValue(); - return SetHTMLAttribute(aAttribute, val, aNotify); - } - - // don't do any update if old == new - result = GetAttr(aNameSpaceID, aAttribute, strValue); - if ((NS_CONTENT_ATTR_NOT_THERE != result) && aValue.Equals(strValue)) { - return NS_OK; - } - - modification = (result != NS_CONTENT_ATTR_NOT_THERE); - - if (aNotify && (nsnull != mDocument)) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - - mDocument->AttributeWillChange(this, aNameSpaceID, aAttribute); - } - - // set as string value to avoid another string copy - PRBool mapped = HasAttributeDependentStyle(aAttribute); - - nsCOMPtr sheet = - dont_AddRef(GetAttrStyleSheet(mDocument)); - - if (!mAttributes) { - result = NS_NewHTMLAttributes(&mAttributes); - NS_ENSURE_SUCCESS(result, result); - } - result = mAttributes->SetAttributeFor(aAttribute, aValue, mapped, - this, sheet); + if (ParseCommonAttribute(aAttribute, aValue, val)) { + // string value was mapped to nsHTMLValue, set it that way + return SetHTMLAttribute(aAttribute, val, aNotify); } + if (aValue.IsEmpty()) { // if empty string + val.SetEmptyValue(); + return SetHTMLAttribute(aAttribute, val, aNotify); + } + + // don't do any update if old == new + result = GetAttr(aNameSpaceID, aAttribute, strValue); + if ((NS_CONTENT_ATTR_NOT_THERE != result) && aValue.Equals(strValue)) { + return NS_OK; + } + + modification = (result != NS_CONTENT_ATTR_NOT_THERE); + + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + if (aNotify && mDocument) { + mDocument->AttributeWillChange(this, aNameSpaceID, aAttribute); + } + + // set as string value to avoid another string copy + PRBool mapped = HasAttributeDependentStyle(aAttribute); + + nsCOMPtr sheet = + dont_AddRef(GetAttrStyleSheet(mDocument)); + + if (!mAttributes) { + result = NS_NewHTMLAttributes(&mAttributes); + NS_ENSURE_SUCCESS(result, result); + } + result = mAttributes->SetAttributeFor(aAttribute, aValue, mapped, + this, sheet); if (mDocument) { nsCOMPtr bindingManager; mDocument->GetBindingManager(getter_AddRefs(bindingManager)); @@ -1757,7 +1755,6 @@ nsGenericHTMLElement::SetAttr(PRInt32 aNameSpaceID, PRInt32(nsIDOMMutationEvent::ADDITION); mDocument->AttributeChanged(this, aNameSpaceID, aAttribute, modHint); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } @@ -1795,8 +1792,9 @@ nsGenericHTMLElement::SetAttr(nsINodeInfo* aNodeInfo, PRBool modification = (rv != NS_CONTENT_ATTR_NOT_THERE); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + if (aNotify && mDocument) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); mDocument->AttributeWillChange(this, namespaceID, localName); } @@ -1851,7 +1849,6 @@ nsGenericHTMLElement::SetAttr(nsINodeInfo* aNodeInfo, modification ? PRInt32(nsIDOMMutationEvent::MODIFICATION) : PRInt32(nsIDOMMutationEvent::ADDITION); mDocument->AttributeChanged(this, namespaceID, localName, modHint); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } @@ -1945,9 +1942,10 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute, (NS_CONTENT_ATTR_NOT_THERE != GetAttr(kNameSpaceID_None, aAttribute, oldValueStr)); } - if (aNotify) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + if (aNotify) { mDocument->AttributeWillChange(this, kNameSpaceID_None, aAttribute); } sheet = dont_AddRef(GetAttrStyleSheet(mDocument)); @@ -2004,7 +2002,6 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute, if (aNotify) { mDocument->AttributeChanged(this, kNameSpaceID_None, aAttribute, nsIDOMMutationEvent::MODIFICATION); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } if (!sheet) { // manage this ourselves and re-sync when we connect to doc @@ -2041,10 +2038,9 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, } } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); if (mDocument) { if (aNotify) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - mDocument->AttributeWillChange(this, aNameSpaceID, aAttribute); } @@ -2098,7 +2094,6 @@ nsGenericHTMLElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, if (aNotify) { mDocument->AttributeChanged(this, aNameSpaceID, aAttribute, nsIDOMMutationEvent::REMOVAL); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } @@ -3700,9 +3695,9 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid, { NS_PRECONDITION(nsnull != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/ if (rv) { NS_ADDREF(aKid); @@ -3729,9 +3724,6 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid, } } } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } return NS_OK; } @@ -3745,9 +3737,8 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid, nsIContent* oldKid = NS_STATIC_CAST(nsIContent *, mChildren.SafeElementAt(aIndex)); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + nsRange::OwnerChildReplaced(this, aIndex, oldKid); PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex); if (rv) { @@ -3777,9 +3768,7 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid, NS_RELEASE(oldKid); } } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } + return NS_OK; } @@ -3789,9 +3778,8 @@ nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, { NS_PRECONDITION(nsnull != aKid && this != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + PRBool rv = mChildren.AppendElement(aKid); if (rv) { NS_ADDREF(aKid); @@ -3818,9 +3806,6 @@ nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, } } } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } return NS_OK; } @@ -3828,9 +3813,8 @@ NS_IMETHODIMP nsGenericHTMLContainerElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) { nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + nsIContent* oldKid = NS_STATIC_CAST(nsIContent *, mChildren.SafeElementAt(aIndex)); if (nsnull != oldKid ) { @@ -3862,9 +3846,6 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) oldKid->SetParent(nsnull); NS_RELEASE(oldKid); } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } return NS_OK; } diff --git a/content/html/content/src/nsHTMLUnknownElement.cpp b/content/html/content/src/nsHTMLUnknownElement.cpp index e9e7de91ed45..01d57064ebe0 100644 --- a/content/html/content/src/nsHTMLUnknownElement.cpp +++ b/content/html/content/src/nsHTMLUnknownElement.cpp @@ -197,9 +197,9 @@ nsHTMLUnknownElement::SetAttribute(PRInt32 aNameSpaceID, return result; } - if (aNotify && (mDocument)) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); - + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + + if (aNotify && mDocument) { mDocument->AttributeWillChange(this, aNameSpaceID, aAttribute); } @@ -215,10 +215,9 @@ nsHTMLUnknownElement::SetAttribute(PRInt32 aNameSpaceID, this, sheet); } - if (aNotify && (mDocument)) { + if (aNotify && mDocument) { result = mDocument->AttributeChanged(this, aNameSpaceID, aAttribute, nsIDOMMutationEvent::MODIFICATION); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } return result; diff --git a/content/html/style/src/nsCSSStyleRule.cpp b/content/html/style/src/nsCSSStyleRule.cpp index 729079a6b8a5..c827ee95d2b1 100644 --- a/content/html/style/src/nsCSSStyleRule.cpp +++ b/content/html/style/src/nsCSSStyleRule.cpp @@ -1032,9 +1032,7 @@ DOMCSSDeclarationImpl::DeclarationChanged() sheet->GetOwningDocument(*getter_AddRefs(owningDoc)); } - if (owningDoc) { - owningDoc->BeginUpdate(UPDATE_STYLE); - } + mozAutoDocUpdate updateBatch(owningDoc, UPDATE_STYLE, PR_TRUE); nsCOMPtr oldRule = mRule; mRule = oldRule->DeclarationChanged(PR_TRUE).get(); @@ -1049,7 +1047,6 @@ DOMCSSDeclarationImpl::DeclarationChanged() if (owningDoc) { owningDoc->StyleRuleChanged(sheet, oldRule, mRule); - owningDoc->EndUpdate(UPDATE_STYLE); } return NS_OK; } diff --git a/content/html/style/src/nsCSSStyleSheet.cpp b/content/html/style/src/nsCSSStyleSheet.cpp index f43aed02947a..dae5b4182efa 100644 --- a/content/html/style/src/nsCSSStyleSheet.cpp +++ b/content/html/style/src/nsCSSStyleSheet.cpp @@ -1037,8 +1037,6 @@ class DOMMediaListImpl : public nsIDOMMediaList, virtual ~DOMMediaListImpl(); private: - nsresult BeginMediaChange(void); - nsresult EndMediaChange(void); nsresult Delete(const nsAString & aOldMedium); nsresult Append(const nsAString & aOldMedium); @@ -1207,19 +1205,44 @@ DOMMediaListImpl::GetMediaText(nsAString& aMediaText) return GetText(aMediaText); } +// "sheet" should be an CSSStyleSheetImpl and "doc" should be an +// nsCOMPtr +#define BEGIN_MEDIA_CHANGE(sheet, doc) \ + if (sheet) { \ + rv = sheet->GetOwningDocument(*getter_AddRefs(doc)); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } \ + mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, PR_TRUE); \ + if (sheet) { \ + rv = sheet->WillDirty(); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } + +#define END_MEDIA_CHANGE(sheet, doc) \ + if (sheet) { \ + sheet->DidDirty(); \ + } \ + /* XXXldb Pass something meaningful? */ \ + if (doc) { \ + rv = doc->StyleRuleChanged(sheet, nsnull, nsnull); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } + + NS_IMETHODIMP DOMMediaListImpl::SetMediaText(const nsAString& aMediaText) { - nsresult rv; - rv = BeginMediaChange(); - if (NS_FAILED(rv)) - return rv; - + nsresult rv = NS_OK; + nsCOMPtr doc; + + BEGIN_MEDIA_CHANGE(mStyleSheet, doc) + rv = SetText(aMediaText); if (NS_FAILED(rv)) return rv; - rv = EndMediaChange(); + END_MEDIA_CHANGE(mStyleSheet, doc) + return rv; } @@ -1260,32 +1283,34 @@ DOMMediaListImpl::Item(PRUint32 aIndex, nsAString& aReturn) NS_IMETHODIMP DOMMediaListImpl::DeleteMedium(const nsAString& aOldMedium) { - nsresult rv; - rv = BeginMediaChange(); - if (NS_FAILED(rv)) - return rv; + nsresult rv = NS_OK; + nsCOMPtr doc; + + BEGIN_MEDIA_CHANGE(mStyleSheet, doc) rv = Delete(aOldMedium); if (NS_FAILED(rv)) return rv; - rv = EndMediaChange(); + END_MEDIA_CHANGE(mStyleSheet, doc) + return rv; } NS_IMETHODIMP DOMMediaListImpl::AppendMedium(const nsAString& aNewMedium) { - nsresult rv; - rv = BeginMediaChange(); - if (NS_FAILED(rv)) - return rv; + nsresult rv = NS_OK; + nsCOMPtr doc; + + BEGIN_MEDIA_CHANGE(mStyleSheet, doc) rv = Append(aNewMedium); if (NS_FAILED(rv)) return rv; - rv = EndMediaChange(); + END_MEDIA_CHANGE(mStyleSheet, doc) + return rv; } @@ -1329,41 +1354,6 @@ DOMMediaListImpl::Append(const nsAString& aNewMedium) return NS_OK; } -nsresult -DOMMediaListImpl::BeginMediaChange(void) -{ - nsresult rv; - nsCOMPtr doc; - - if (mStyleSheet) { - rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); - NS_ENSURE_SUCCESS(rv, rv); - rv = doc->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(rv, rv); - rv = mStyleSheet->WillDirty(); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; -} - -nsresult -DOMMediaListImpl::EndMediaChange(void) -{ - nsresult rv; - nsCOMPtr doc; - if (mStyleSheet) { - mStyleSheet->DidDirty(); - rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); - NS_ENSURE_SUCCESS(rv, rv); - // XXXldb Pass something meaningful? - rv = doc->StyleRuleChanged(mStyleSheet, nsnull, nsnull); - NS_ENSURE_SUCCESS(rv, rv); - rv = doc->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; -} - // ------------------------------- // Imports Collection for the DOM // @@ -2672,11 +2662,7 @@ CSSStyleSheetImpl::InsertRule(const nsAString& aRule, if (NS_FAILED(result)) return result; - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - if (NS_FAILED(result)) - return result; - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); nsCOMPtr rules; result = css->ParseRule(aRule, mInner->mURL, getter_AddRefs(rules)); @@ -2799,11 +2785,6 @@ CSSStyleSheetImpl::InsertRule(const nsAString& aRule, } } - if (mDocument) { - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } - if (loader) { loader->RecycleParser(css); } @@ -2825,11 +2806,8 @@ CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) // XXX TBI: handle @rule types if (mInner && mInner->mOrderedRules) { - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - if (NS_FAILED(result)) - return result; - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); + result = WillDirty(); if (NS_SUCCEEDED(result)) { @@ -2848,9 +2826,6 @@ CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) if (mDocument) { result = mDocument->StyleRuleRemoved(this, rule); NS_ENSURE_SUCCESS(result, result); - - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); } } } @@ -2877,11 +2852,8 @@ CSSStyleSheetImpl::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) return NS_ERROR_INVALID_ARG; } - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } - + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); + result = WillDirty(); NS_ENSURE_SUCCESS(result, result); @@ -2895,9 +2867,6 @@ CSSStyleSheetImpl::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) if (mDocument) { result = mDocument->StyleRuleRemoved(this, rule); NS_ENSURE_SUCCESS(result, result); - - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); } return NS_OK; @@ -2936,11 +2905,8 @@ CSSStyleSheetImpl::InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* } NS_ENSURE_SUCCESS(result, result); - // parse and grab the rule - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } + // parse and grab the rule + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); result = WillDirty(); NS_ENSURE_SUCCESS(result, result); @@ -2979,11 +2945,6 @@ CSSStyleSheetImpl::InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* } } - if (mDocument) { - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } - if (loader) { loader->RecycleParser(css); } @@ -3032,17 +2993,13 @@ CSSStyleSheetImpl::StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify) nsCOMPtr ownerRule; aSheet->GetOwnerRule(getter_AddRefs(ownerRule)); - nsresult rv = mDocument->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(rv, rv); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); // XXXldb @import rules shouldn't even implement nsIStyleRule (but // they do)! nsCOMPtr styleRule(do_QueryInterface(ownerRule)); - rv = mDocument->StyleRuleAdded(this, styleRule); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mDocument->EndUpdate(UPDATE_STYLE); + nsresult rv = mDocument->StyleRuleAdded(this, styleRule); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/content/svg/content/src/nsSVGAttributes.cpp b/content/svg/content/src/nsSVGAttributes.cpp index 2f46fdcd9c2b..bd34bcb3d85d 100644 --- a/content/svg/content/src/nsSVGAttributes.cpp +++ b/content/svg/content/src/nsSVGAttributes.cpp @@ -607,8 +607,8 @@ nsSVGAttributes::SetAttr(nsINodeInfo* aNodeInfo, nsCOMPtr name = aNodeInfo->GetNameAtom(); // Send the notification before making any updates + mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); if (aNotify && document) { - document->BeginUpdate(UPDATE_CONTENT_MODEL); document->AttributeWillChange(mContent, nameSpaceID, name); } @@ -671,7 +671,6 @@ nsSVGAttributes::SetAttr(nsINodeInfo* aNodeInfo, : PRInt32(nsIDOMMutationEvent::ADDITION); document->AttributeChanged(mContent, nameSpaceID, name, modHint); - document->EndUpdate(UPDATE_CONTENT_MODEL); } } @@ -687,8 +686,6 @@ nsSVGAttributes::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, return NS_ERROR_NULL_POINTER; } - nsresult rv = NS_OK; - nsCOMPtr document; if (mContent) document = mContent->GetDocument(); @@ -696,47 +693,54 @@ nsSVGAttributes::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRInt32 count = Count(); PRInt32 index; PRBool found = PR_FALSE; + nsSVGAttribute* attr = nsnull; for (index = 0; index < count; index++) { - nsSVGAttribute* attr = ElementAt(index); + attr = ElementAt(index); if ((aNameSpaceID == kNameSpaceID_Unknown || attr->GetNodeInfo()->NamespaceEquals(aNameSpaceID)) && attr->GetNodeInfo()->Equals(aName) && !attr->IsRequired() && !attr->IsFixed()) { - if (aNotify && document) { - document->BeginUpdate(UPDATE_CONTENT_MODEL); - } - - if (mContent && nsGenericElement::HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { - nsCOMPtr node(do_QueryInterface(mContent)); - nsMutationEvent mutation; - mutation.eventStructType = NS_MUTATION_EVENT; - mutation.message = NS_MUTATION_ATTRMODIFIED; - mutation.mTarget = node; - - CallQueryInterface(attr, - NS_STATIC_CAST(nsIDOMNode**, - getter_AddRefs(mutation.mRelatedNode))); - mutation.mAttrName = aName; - nsAutoString str; - attr->GetValue()->GetValueString(str); - if (!str.IsEmpty()) - mutation.mPrevAttrValue = do_GetAtom(str); - mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL; - - nsEventStatus status = nsEventStatus_eIgnore; - nsCOMPtr domEvent; - mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), - NS_EVENT_FLAG_INIT, &status); - } - - RemoveElementAt(index); found = PR_TRUE; break; } } + + if (!found) { + return NS_OK; + } + + mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify); + if (document && aNotify) { + document->AttributeWillChange(mContent, aNameSpaceID, aName); + } - if (NS_SUCCEEDED(rv) && found && document) { + if (mContent && nsGenericElement::HasMutationListeners(mContent, NS_EVENT_BITS_MUTATION_ATTRMODIFIED)) { + nsCOMPtr node(do_QueryInterface(mContent)); + nsMutationEvent mutation; + mutation.eventStructType = NS_MUTATION_EVENT; + mutation.message = NS_MUTATION_ATTRMODIFIED; + mutation.mTarget = node; + + CallQueryInterface(attr, + NS_STATIC_CAST(nsIDOMNode**, + getter_AddRefs(mutation.mRelatedNode))); + mutation.mAttrName = aName; + nsAutoString str; + attr->GetValue()->GetValueString(str); + if (!str.IsEmpty()) + mutation.mPrevAttrValue = do_GetAtom(str); + mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL; + + nsEventStatus status = nsEventStatus_eIgnore; + nsCOMPtr domEvent; + mContent->HandleDOMEvent(nsnull, &mutation, getter_AddRefs(domEvent), + NS_EVENT_FLAG_INIT, &status); + } + + RemoveElementAt(index); + + if (document) { nsCOMPtr bindingManager; document->GetBindingManager(getter_AddRefs(bindingManager)); nsCOMPtr binding; @@ -747,11 +751,10 @@ nsSVGAttributes::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, if (aNotify) { document->AttributeChanged(mContent, aNameSpaceID, aName, nsIDOMMutationEvent::REMOVAL); - document->EndUpdate(UPDATE_CONTENT_MODEL); } } - return rv; + return NS_OK; } NS_IMETHODIMP_(PRBool) diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index e39a5412708d..ee2e29995c51 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -158,9 +158,8 @@ nsSVGElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, { NS_PRECONDITION(nsnull != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/ if (rv) { NS_ADDREF(aKid); @@ -188,9 +187,7 @@ nsSVGElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, } } } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } + return NS_OK; } @@ -201,9 +198,8 @@ nsSVGElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, { NS_PRECONDITION(nsnull != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != mDocument)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); nsRange::OwnerChildReplaced(this, aIndex, oldKid); PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex); @@ -220,9 +216,6 @@ nsSVGElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, oldKid->SetParent(nsnull); NS_RELEASE(oldKid); } - if (aNotify && (nsnull != mDocument)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } return NS_OK; } @@ -232,9 +225,8 @@ nsSVGElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, { NS_PRECONDITION(nsnull != aKid && this != aKid, "null ptr"); nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); + PRBool rv = mChildren.AppendElement(aKid); if (rv) { NS_ADDREF(aKid); @@ -262,9 +254,7 @@ nsSVGElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, } } } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } + return NS_OK; } @@ -272,11 +262,10 @@ NS_IMETHODIMP nsSVGElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) { nsIDocument* doc = mDocument; - if (aNotify && (nsnull != doc)) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); - } + nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex); if (nsnull != oldKid ) { + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEREMOVED)) { nsCOMPtr node(do_QueryInterface(oldKid)); @@ -306,9 +295,6 @@ nsSVGElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) oldKid->SetParent(nsnull); NS_RELEASE(oldKid); } - if (aNotify && (nsnull != doc)) { - doc->EndUpdate(UPDATE_CONTENT_MODEL); - } return NS_OK; } diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index d80ebb3697cf..950102e9e74b 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -1950,6 +1950,8 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, // freak out. NS_ASSERTION(mChildren.IndexOf(aKid) < 0, "element is already a child"); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + if (!mChildren.InsertElementAt(aKid, aIndex)) return NS_ERROR_FAILURE; @@ -2001,6 +2003,9 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify, if (oldKid == aKid) return NS_OK; + //XXXbz should this fire DOMSubtreeModified? + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + PRBool replaceOk = mChildren.ReplaceElementAt(aKid, aIndex); if (replaceOk) { NS_ADDREF(aKid); @@ -2033,6 +2038,8 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify, PRBool aDeepSetDoc NS_PRECONDITION((nsnull != aKid) && (aKid != NS_STATIC_CAST(nsIStyledContent*, this)), "null ptr"); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + PRBool appendOk = mChildren.AppendElement(aKid); if (appendOk) { NS_ADDREF(aKid); @@ -2074,6 +2081,8 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify) if (! oldKid) return NS_ERROR_FAILURE; + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + if (HasMutationListeners(NS_STATIC_CAST(nsIStyledContent*,this), NS_EVENT_BITS_MUTATION_NODEREMOVED)) { nsCOMPtr node(do_QueryInterface(oldKid)); nsMutationEvent mutation; @@ -2334,8 +2343,8 @@ nsXULElement::SetAttr(nsINodeInfo* aNodeInfo, } // Send the update notification _before_ changing anything + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); if (mDocument && aNotify) { - mDocument->BeginUpdate(UPDATE_CONTENT_MODEL); mDocument->AttributeWillChange(this, attrns, attrName); } @@ -2433,7 +2442,6 @@ nsXULElement::SetAttr(nsINodeInfo* aNodeInfo, : PRInt32(nsIDOMMutationEvent::ADDITION); mDocument->AttributeChanged(this, attrns, attrName, modHint); - mDocument->EndUpdate(UPDATE_CONTENT_MODEL); } } @@ -2620,17 +2628,20 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, // Deal with modification of magical attributes that side-effect // other things. // - // XXXwaterson if aNotify == PR_TRUE, do we want to call - // nsIDocument::BeginUpdate() now? + mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, aNotify); + if (mDocument && aNotify) { + mDocument->AttributeWillChange(this, aNameSpaceID, aName); + } + if (aNameSpaceID == kNameSpaceID_None) { if (aName == nsXULAtoms::clazz) { // If CLASS is being unset, delete our class list. - Attributes()->UpdateClassList(nsAutoString()); + Attributes()->UpdateClassList(NS_LITERAL_STRING("")); } else if (aName == nsXULAtoms::style) { nsCOMPtr baseURL; GetBaseURL(getter_AddRefs(baseURL)); - Attributes()->UpdateStyleRule(baseURL, nsAutoString()); - // XXX Some kind of special document update might need to happen here. + Attributes()->UpdateStyleRule(baseURL, NS_LITERAL_STRING("")); + // AttributeChanged() will handle the style reresolution } } @@ -2710,8 +2721,6 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, if (aNotify) { mDocument->AttributeChanged(this, aNameSpaceID, aName, nsIDOMMutationEvent::REMOVAL); - - // XXXwaterson do we need to mDocument->EndUpdate() here? } } diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 975707378fd1..ccfd846bf658 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -284,9 +284,9 @@ nsHTMLFramesetFrame::Observe(nsISupports* aObject, const char* aAction, { nsAutoString prefName(aPrefName); if (prefName.Equals(NS_LITERAL_STRING(kFrameResizePref))) { - nsCOMPtr doc = mContent->GetDocument(); + nsIDocument* doc = mContent->GetDocument(); + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE); if (doc) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); doc->AttributeWillChange(mContent, kNameSpaceID_None, nsHTMLAtoms::frameborder); @@ -301,7 +301,6 @@ nsHTMLFramesetFrame::Observe(nsISupports* aObject, const char* aAction, kNameSpaceID_None, nsHTMLAtoms::frameborder, nsIDOMMutationEvent::MODIFICATION); - doc->EndUpdate(UPDATE_CONTENT_MODEL); } } return NS_OK; diff --git a/layout/html/document/src/nsFrameSetFrame.cpp b/layout/html/document/src/nsFrameSetFrame.cpp index 975707378fd1..ccfd846bf658 100644 --- a/layout/html/document/src/nsFrameSetFrame.cpp +++ b/layout/html/document/src/nsFrameSetFrame.cpp @@ -284,9 +284,9 @@ nsHTMLFramesetFrame::Observe(nsISupports* aObject, const char* aAction, { nsAutoString prefName(aPrefName); if (prefName.Equals(NS_LITERAL_STRING(kFrameResizePref))) { - nsCOMPtr doc = mContent->GetDocument(); + nsIDocument* doc = mContent->GetDocument(); + mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE); if (doc) { - doc->BeginUpdate(UPDATE_CONTENT_MODEL); doc->AttributeWillChange(mContent, kNameSpaceID_None, nsHTMLAtoms::frameborder); @@ -301,7 +301,6 @@ nsHTMLFramesetFrame::Observe(nsISupports* aObject, const char* aAction, kNameSpaceID_None, nsHTMLAtoms::frameborder, nsIDOMMutationEvent::MODIFICATION); - doc->EndUpdate(UPDATE_CONTENT_MODEL); } } return NS_OK; diff --git a/layout/style/nsCSSStyleRule.cpp b/layout/style/nsCSSStyleRule.cpp index 729079a6b8a5..c827ee95d2b1 100644 --- a/layout/style/nsCSSStyleRule.cpp +++ b/layout/style/nsCSSStyleRule.cpp @@ -1032,9 +1032,7 @@ DOMCSSDeclarationImpl::DeclarationChanged() sheet->GetOwningDocument(*getter_AddRefs(owningDoc)); } - if (owningDoc) { - owningDoc->BeginUpdate(UPDATE_STYLE); - } + mozAutoDocUpdate updateBatch(owningDoc, UPDATE_STYLE, PR_TRUE); nsCOMPtr oldRule = mRule; mRule = oldRule->DeclarationChanged(PR_TRUE).get(); @@ -1049,7 +1047,6 @@ DOMCSSDeclarationImpl::DeclarationChanged() if (owningDoc) { owningDoc->StyleRuleChanged(sheet, oldRule, mRule); - owningDoc->EndUpdate(UPDATE_STYLE); } return NS_OK; } diff --git a/layout/style/nsCSSStyleSheet.cpp b/layout/style/nsCSSStyleSheet.cpp index f43aed02947a..dae5b4182efa 100644 --- a/layout/style/nsCSSStyleSheet.cpp +++ b/layout/style/nsCSSStyleSheet.cpp @@ -1037,8 +1037,6 @@ class DOMMediaListImpl : public nsIDOMMediaList, virtual ~DOMMediaListImpl(); private: - nsresult BeginMediaChange(void); - nsresult EndMediaChange(void); nsresult Delete(const nsAString & aOldMedium); nsresult Append(const nsAString & aOldMedium); @@ -1207,19 +1205,44 @@ DOMMediaListImpl::GetMediaText(nsAString& aMediaText) return GetText(aMediaText); } +// "sheet" should be an CSSStyleSheetImpl and "doc" should be an +// nsCOMPtr +#define BEGIN_MEDIA_CHANGE(sheet, doc) \ + if (sheet) { \ + rv = sheet->GetOwningDocument(*getter_AddRefs(doc)); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } \ + mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, PR_TRUE); \ + if (sheet) { \ + rv = sheet->WillDirty(); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } + +#define END_MEDIA_CHANGE(sheet, doc) \ + if (sheet) { \ + sheet->DidDirty(); \ + } \ + /* XXXldb Pass something meaningful? */ \ + if (doc) { \ + rv = doc->StyleRuleChanged(sheet, nsnull, nsnull); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } + + NS_IMETHODIMP DOMMediaListImpl::SetMediaText(const nsAString& aMediaText) { - nsresult rv; - rv = BeginMediaChange(); - if (NS_FAILED(rv)) - return rv; - + nsresult rv = NS_OK; + nsCOMPtr doc; + + BEGIN_MEDIA_CHANGE(mStyleSheet, doc) + rv = SetText(aMediaText); if (NS_FAILED(rv)) return rv; - rv = EndMediaChange(); + END_MEDIA_CHANGE(mStyleSheet, doc) + return rv; } @@ -1260,32 +1283,34 @@ DOMMediaListImpl::Item(PRUint32 aIndex, nsAString& aReturn) NS_IMETHODIMP DOMMediaListImpl::DeleteMedium(const nsAString& aOldMedium) { - nsresult rv; - rv = BeginMediaChange(); - if (NS_FAILED(rv)) - return rv; + nsresult rv = NS_OK; + nsCOMPtr doc; + + BEGIN_MEDIA_CHANGE(mStyleSheet, doc) rv = Delete(aOldMedium); if (NS_FAILED(rv)) return rv; - rv = EndMediaChange(); + END_MEDIA_CHANGE(mStyleSheet, doc) + return rv; } NS_IMETHODIMP DOMMediaListImpl::AppendMedium(const nsAString& aNewMedium) { - nsresult rv; - rv = BeginMediaChange(); - if (NS_FAILED(rv)) - return rv; + nsresult rv = NS_OK; + nsCOMPtr doc; + + BEGIN_MEDIA_CHANGE(mStyleSheet, doc) rv = Append(aNewMedium); if (NS_FAILED(rv)) return rv; - rv = EndMediaChange(); + END_MEDIA_CHANGE(mStyleSheet, doc) + return rv; } @@ -1329,41 +1354,6 @@ DOMMediaListImpl::Append(const nsAString& aNewMedium) return NS_OK; } -nsresult -DOMMediaListImpl::BeginMediaChange(void) -{ - nsresult rv; - nsCOMPtr doc; - - if (mStyleSheet) { - rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); - NS_ENSURE_SUCCESS(rv, rv); - rv = doc->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(rv, rv); - rv = mStyleSheet->WillDirty(); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; -} - -nsresult -DOMMediaListImpl::EndMediaChange(void) -{ - nsresult rv; - nsCOMPtr doc; - if (mStyleSheet) { - mStyleSheet->DidDirty(); - rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); - NS_ENSURE_SUCCESS(rv, rv); - // XXXldb Pass something meaningful? - rv = doc->StyleRuleChanged(mStyleSheet, nsnull, nsnull); - NS_ENSURE_SUCCESS(rv, rv); - rv = doc->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(rv, rv); - } - return NS_OK; -} - // ------------------------------- // Imports Collection for the DOM // @@ -2672,11 +2662,7 @@ CSSStyleSheetImpl::InsertRule(const nsAString& aRule, if (NS_FAILED(result)) return result; - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - if (NS_FAILED(result)) - return result; - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); nsCOMPtr rules; result = css->ParseRule(aRule, mInner->mURL, getter_AddRefs(rules)); @@ -2799,11 +2785,6 @@ CSSStyleSheetImpl::InsertRule(const nsAString& aRule, } } - if (mDocument) { - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } - if (loader) { loader->RecycleParser(css); } @@ -2825,11 +2806,8 @@ CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) // XXX TBI: handle @rule types if (mInner && mInner->mOrderedRules) { - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - if (NS_FAILED(result)) - return result; - } + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); + result = WillDirty(); if (NS_SUCCEEDED(result)) { @@ -2848,9 +2826,6 @@ CSSStyleSheetImpl::DeleteRule(PRUint32 aIndex) if (mDocument) { result = mDocument->StyleRuleRemoved(this, rule); NS_ENSURE_SUCCESS(result, result); - - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); } } } @@ -2877,11 +2852,8 @@ CSSStyleSheetImpl::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) return NS_ERROR_INVALID_ARG; } - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } - + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); + result = WillDirty(); NS_ENSURE_SUCCESS(result, result); @@ -2895,9 +2867,6 @@ CSSStyleSheetImpl::DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) if (mDocument) { result = mDocument->StyleRuleRemoved(this, rule); NS_ENSURE_SUCCESS(result, result); - - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); } return NS_OK; @@ -2936,11 +2905,8 @@ CSSStyleSheetImpl::InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* } NS_ENSURE_SUCCESS(result, result); - // parse and grab the rule - if (mDocument) { - result = mDocument->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } + // parse and grab the rule + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); result = WillDirty(); NS_ENSURE_SUCCESS(result, result); @@ -2979,11 +2945,6 @@ CSSStyleSheetImpl::InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* } } - if (mDocument) { - result = mDocument->EndUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(result, result); - } - if (loader) { loader->RecycleParser(css); } @@ -3032,17 +2993,13 @@ CSSStyleSheetImpl::StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify) nsCOMPtr ownerRule; aSheet->GetOwnerRule(getter_AddRefs(ownerRule)); - nsresult rv = mDocument->BeginUpdate(UPDATE_STYLE); - NS_ENSURE_SUCCESS(rv, rv); + mozAutoDocUpdate updateBatch(mDocument, UPDATE_STYLE, PR_TRUE); // XXXldb @import rules shouldn't even implement nsIStyleRule (but // they do)! nsCOMPtr styleRule(do_QueryInterface(ownerRule)); - rv = mDocument->StyleRuleAdded(this, styleRule); - NS_ENSURE_SUCCESS(rv, rv); - - rv = mDocument->EndUpdate(UPDATE_STYLE); + nsresult rv = mDocument->StyleRuleAdded(this, styleRule); NS_ENSURE_SUCCESS(rv, rv); }