Closed Bug 131775 Opened 23 years ago Closed 21 years ago

[FIX]BeginUpdate is not always matched by EndUpdate in DOM code

Categories

(Core :: DOM: Core & HTML, defect, P1)

defect

Tracking

()

RESOLVED FIXED
mozilla1.6alpha

People

(Reporter: bzbarsky, Assigned: bzbarsky)

References

Details

Attachments

(2 files, 2 obsolete files)

We have a few places in our code where we BeginUpdate() but may not EndUpdate(): nsSVGAttributes::SetAttr nsSVGAttributes::UnsetAttr DOMMediaListImpl::BeginMediaChange/DOMMediaListImpl::EndMediaChange (the latter is not always called by the medialist manipulation methods) DOMCSSDeclarationImpl::ParsePropertyValue CSSStyleSheetImpl::InsertRule CSSStyleSheetImpl::DeleteRule CSSStyleSheetImpl::DeleteRuleFromGroup CSSStyleSheetImpl::InsertRuleIntoGroup nsGenericContainerElement::UnsetAttr nsGenericContainerElement::SetAttr Not assigning this to myself because I don't have time to do this till sometime in mid-May and some of that code is hairy, but feel free to punt to me if this is not a priority and if you're not going to get to it till then anyway, jst.
Mass-reassigning bugs to dom_bugs@netscape.com
Assignee: jst → dom_bugs
I guess I may as well take this....
Assignee: dom_bugs → bzbarsky
Should we write a little nsAutoUpdate (or whatever) class to help here?
Yeah, that was what I was thinking... I was gonna call it nsContentUpdateBatch, maybe... (or just nsUpdateBatch).
Priority: -- → P1
Target Milestone: --- → mozilla1.5alpha
Depends on: 200931
Attached patch Patch (obsolete) — Splinter Review
This introduces the mozAutoDocUpdate class and uses it in various places.
Attached patch Same as diff -w FOR REVIEW ONLY (obsolete) — Splinter Review
Comment on attachment 132561 [details] [diff] [review] Same as diff -w FOR REVIEW ONLY reviews?
Attachment #132561 - Flags: superreview?(jst)
Attachment #132561 - Flags: review?(caillon)
Incidentally, this fixes bug 211022
Blocks: 211022
Summary: BeginUpdate is not always matched by EndUpdate in DOM code → [FIX]BeginUpdate is not always matched by EndUpdate in DOM code
Target Milestone: mozilla1.5alpha → mozilla1.6alpha
Comment on attachment 132561 [details] [diff] [review] Same as diff -w FOR REVIEW ONLY This patch is bogus...
Attachment #132561 - Flags: superreview?(jst)
Attachment #132561 - Flags: review?(caillon)
Attachment #132560 - Attachment is obsolete: true
Attachment #132561 - Attachment is obsolete: true
Attachment #132623 - Flags: superreview?(jst)
Attachment #132623 - Flags: review?(caillon)
Attachment #132561 - Flags: superreview?(jst)
Attachment #132561 - Flags: review?(caillon)
Attachment #132561 - Flags: superreview?(jst)
Attachment #132561 - Flags: review?(caillon)
Comment on attachment 132623 [details] [diff] [review] Same as diff -w FOR REVIEW ONLY General comment: It seems there are quite a few callsites, (though most prominent in nsSVGElement) where things are similar to: A::DoFoo() { mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, aNotify); if (foo) { // Do things which will send notifications } } I think that in these cases, you can either use early returns if (!foo) since nothing will happen to get rid of the extra scope, or move the mozAutoDocUpdate inside the if so that we don't tell the document there will be udpates when there really won't be. There are cases in other places where you can't do an early return, so I would just recommend changing the scope. Let's send as few notifications to observers as possible. :-) >Index: content/base/public/nsIDocument.h > // 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. Hm, I never thought I would make a nit this anal, but... Could you move the "To" in the above comment down to the next line? It seems to dangle out there. Sorry, I used to work at a newspaper a few years back and that was one of the guidelines of making things more readable we tried to follow (not ending a line with the first word of a multi-word statement when said word is a short one), and I tend to agree that it makes it easier to read. > NS_IMETHOD BeginUpdate(nsUpdateType aUpdateType) = 0; > NS_IMETHOD EndUpdate(nsUpdateType aUpdateType) = 0; > NS_IMETHOD BeginLoad() = 0; > NS_IMETHOD EndLoad() = 0; > NS_IMETHOD ContentChanged(nsIContent* aContent, > nsISupports* aSubContent) = 0; > // notify that one or two content nodes changed state > // either may be nsnull, but not both > NS_IMETHOD ContentStatesChanged(nsIContent* aContent1, > nsIContent* aContent2, >@@ -467,20 +469,43 @@ public: > const nsAString& Standalone) = 0; > NS_IMETHOD GetXMLDeclaration(nsAString& aVersion, > nsAString& aEncoding, > nsAString& Standalone) = 0; > > NS_IMETHOD_(PRBool) IsCaseSensitive() = 0; > > NS_IMETHOD_(PRBool) IsScriptEnabled() = 0; > }; > >+class mozAutoDocUpdate { Brace on its own line? Also, could you please document we allow mDocument to be null so that we don't have to null-check (and therefore add another scope) in all the callers? >+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<nsIDocument> mDocument; >+ nsUpdateType mUpdateType; >+}; > > // XXX These belong somewhere else > nsresult > NS_NewHTMLDocument(nsIDocument** aInstancePtrResult); > > nsresult > NS_NewXMLDocument(nsIDocument** aInstancePtrResult); > > #ifdef MOZ_SVG > nsresult >Index: content/base/src/nsGenericElement.cpp >=================================================================== >RCS file: /cvsroot/mozilla/content/base/src/nsGenericElement.cpp,v >retrieving revision 3.291 >diff -p -u -1 -0 -w -r3.291 nsGenericElement.cpp >--- content/base/src/nsGenericElement.cpp 2 Oct 2003 21:29:31 -0000 3.291 >+++ content/base/src/nsGenericElement.cpp 4 Oct 2003 08:23:41 -0000 >@@ -2606,23 +2606,24 @@ nsGenericElement::doInsertBefore(nsIDOMN > NS_ENSURE_TRUE(doc_fragment, NS_ERROR_UNEXPECTED); > > doc_fragment->DisconnectChildren(); > > PRUint32 count = newContent->GetChildCount(); > > PRUint32 old_count = GetChildCount(); > > 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... So pass !do_notify as aNotify. I guess technically, you're only passing !do_notify if there are children. Also is the reader of the comment supposed to know where |aNotify| comes from? >+ mozAutoDocUpdate updateBatch(mDocument, UPDATE_CONTENT_MODEL, >+ count && !do_notify); >Index: content/html/style/src/nsCSSStyleSheet.cpp >+#define BEGIN_MEDIA_CHANGE() \ >+ if (mStyleSheet) { \ >+ rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); \ >+ NS_ENSURE_SUCCESS(rv, rv); \ >+ } \ >+ mozAutoDocUpdate updateBatch(doc, UPDATE_STYLE, PR_TRUE); \ >+ if (mStyleSheet) { \ >+ rv = mStyleSheet->WillDirty(); \ >+ NS_ENSURE_SUCCESS(rv, rv); \ >+ } >+ >+#define END_MEDIA_CHANGE() \ >+ if (mStyleSheet) { \ >+ mStyleSheet->DidDirty(); \ >+ } \ >+ /* XXXldb Pass something meaningful? */ \ >+ if (doc) { \ >+ rv = doc->StyleRuleChanged(mStyleSheet, nsnull, nsnull); \ >+ NS_ENSURE_SUCCESS(rv, rv); \ >+ } >+ How about making mStyleSheet and doc be parameters to the macros? This way it makes the call-sites more explicit as to what is going on, and doesn't rely on a local being defined |doc| at each call site, though it doesn't really matter much since you name the variable the same thing everywhere.... Does this also need PR_BEGIN_MACRO and PR_END_MACRO?
Oh duh, can't use PR_BEGIN/END_MACRO because of scoping.
> though most prominent in nsSVGElement There is only one callsite in nsSVGElement where I could change the scope (in nsSVGElement::RemoveChildAt). The rest are correct, in fact. Added comments about mozAutoDocUpdate. > Also is the reader of the comment supposed to know where |aNotify| comes from? Made comment clearer. > How about making mStyleSheet and doc be parameters to the macros? Good idea. Done.
Comment on attachment 132623 [details] [diff] [review] Same as diff -w FOR REVIEW ONLY (btw, that was r= with comments fixed)
Attachment #132623 - Flags: review?(caillon) → review+
Comment on attachment 132623 [details] [diff] [review] Same as diff -w FOR REVIEW ONLY sr=jst
Attachment #132623 - Flags: superreview?(jst) → superreview+
Checked in, with caillon's review comments addressed.
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
Component: DOM → DOM: Core & HTML
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: