From bdd3e9637bf93a034a880a65eea41119dc98a34f Mon Sep 17 00:00:00 2001 From: "Olli.Pettay@helsinki.fi" Date: Thu, 14 Feb 2008 12:45:07 -0800 Subject: [PATCH] Bug 409111, WRONG_DOCUMENT_ERR on unattached nodes through getBoxObjectFor, r+sr=sicking, a=mtschrep --- content/base/src/nsDocument.cpp | 38 +++++++++++++++++---- content/base/src/nsDocument.h | 4 ++- content/base/src/nsGenericElement.cpp | 3 -- content/base/src/nsNodeUtils.cpp | 10 ++++++ content/xul/content/src/nsXULElement.cpp | 4 +-- dom/locales/en-US/chrome/dom/dom.properties | 1 + 6 files changed, 46 insertions(+), 14 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 1b57992107a..cf7a5215bb2 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -785,6 +785,15 @@ nsDocument::nsDocument(const char* aContentType) SetDOMStringToNull(mLastStyleSheetSet); } +PR_STATIC_CALLBACK(PLDHashOperator) +ClearAllBoxObjects(const void* aKey, nsPIBoxObject* aBoxObject, void* aUserArg) +{ + if (aBoxObject) { + aBoxObject->Clear(); + } + return PL_DHASH_NEXT; +} + nsDocument::~nsDocument() { #ifdef PR_LOGGING @@ -876,7 +885,12 @@ nsDocument::~nsDocument() } delete mHeaderData; - delete mBoxObjectTable; + + if (mBoxObjectTable) { + mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nsnull); + delete mBoxObjectTable; + } + delete mContentWrapperHash; } @@ -919,12 +933,11 @@ RadioGroupsTraverser(const nsAString& aKey, nsAutoPtr& aData } PR_STATIC_CALLBACK(PLDHashOperator) -BoxObjectTraverser(nsISupports* key, nsPIBoxObject* boxObject, void* userArg) +BoxObjectTraverser(const void* key, nsPIBoxObject* boxObject, void* userArg) { nsCycleCollectionTraversalCallback *cb = static_cast(userArg); - cb->NoteXPCOMChild(key); cb->NoteXPCOMChild(boxObject); return PL_DHASH_NEXT; @@ -3662,14 +3675,25 @@ nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) nsCOMPtr content(do_QueryInterface(aElement)); NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED); - nsIDocument* doc = content->HasFlag(NODE_FORCE_XBL_BINDINGS) ? - content->GetOwnerDoc() : content->GetCurrentDoc(); + nsIDocument* doc = content->GetOwnerDoc(); NS_ENSURE_TRUE(doc == this, NS_ERROR_DOM_WRONG_DOCUMENT_ERR); - + + if (!mHasWarnedAboutBoxObjects && !content->IsNodeOfType(eXUL)) { + mHasWarnedAboutBoxObjects = PR_TRUE; + nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES, + "UseOfGetBoxObjectForWarning", + nsnull, 0, + static_cast(this)-> + GetDocumentURI(), + EmptyString(), 0, 0, + nsIScriptError::warningFlag, + "BoxObjects"); + } + *aResult = nsnull; if (!mBoxObjectTable) { - mBoxObjectTable = new nsInterfaceHashtable; + mBoxObjectTable = new nsInterfaceHashtable; if (mBoxObjectTable && !mBoxObjectTable->Init(12)) { mBoxObjectTable = nsnull; } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index d3b6d472d85..1265768616d 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -776,11 +776,13 @@ protected: // True if document has ever had script handling object. PRPackedBool mHasHadScriptHandlingObject:1; + PRPackedBool mHasWarnedAboutBoxObjects:1; + PRUint8 mXMLDeclarationBits; PRUint8 mDefaultElementType; - nsInterfaceHashtable *mBoxObjectTable; + nsInterfaceHashtable *mBoxObjectTable; nsInterfaceHashtable *mContentWrapperHash; // The channel that got passed to StartDocumentLoad(), if any diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 56d198b4ef8..a7754d95719 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -2123,8 +2123,6 @@ nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent) if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) { document->ForgetLink(this); } - - document->ClearBoxObjectFor(this); } // Unset things in the reverse order from how we set them in BindToTree @@ -2891,7 +2889,6 @@ nsGenericElement::DestroyContent() nsIDocument *document = GetOwnerDoc(); if (document) { document->BindingManager()->ChangeDocumentFor(this, document, nsnull); - document->ClearBoxObjectFor(this); } PRUint32 i, count = mAttrsAndChildren.ChildCount(); diff --git a/content/base/src/nsNodeUtils.cpp b/content/base/src/nsNodeUtils.cpp index 445e25d1184..fe875235d18 100755 --- a/content/base/src/nsNodeUtils.cpp +++ b/content/base/src/nsNodeUtils.cpp @@ -235,6 +235,13 @@ nsNodeUtils::LastRelease(nsINode* aNode) aNode->UnsetFlags(NODE_HAS_LISTENERMANAGER); } + if (aNode->IsNodeOfType(nsINode::eELEMENT)) { + nsIDocument* ownerDoc = aNode->GetOwnerDoc(); + if (ownerDoc) { + ownerDoc->ClearBoxObjectFor(static_cast(aNode)); + } + } + delete aNode; } @@ -544,6 +551,9 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep, nsCOMPtr oldRef; nsIDocument* oldDoc = aNode->GetOwnerDoc(); if (oldDoc) { + if (aNode->IsNodeOfType(nsINode::eELEMENT)) { + oldDoc->ClearBoxObjectFor(static_cast(aNode)); + } oldRef = oldDoc->GetReference(aNode); if (oldRef) { oldDoc->RemoveReference(aNode); diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 1e9a98386ea..8c42668ecff 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -1830,9 +1830,7 @@ nsXULElement::GetBoxObject(nsIBoxObject** aResult) *aResult = nsnull; // XXX sXBL/XBL2 issue! Owner or current document? - nsIDocument* doc = HasFlag(NODE_FORCE_XBL_BINDINGS) ? - GetOwnerDoc() : GetCurrentDoc(); - nsCOMPtr nsDoc(do_QueryInterface(doc)); + nsCOMPtr nsDoc = do_QueryInterface(GetOwnerDoc()); return nsDoc ? nsDoc->GetBoxObjectFor(this, aResult) : NS_ERROR_FAILURE; } diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index a69a0c7a54d..ba1de0afd91 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -55,5 +55,6 @@ UseOfReleaseEventsWarning=Use of releaseEvents() is deprecated, see bug 330494. UseOfRouteEventWarning=Use of routeEvent() is deprecated, see bug 330494. UseOfPreventBubbleWarning=Event=%S, use of preventBubble() is deprecated. Use W3C standard stopPropagation() instead. UseOfPreventCaptureWarning=Event=%S, use of preventCapture() is deprecated. Use W3C standard stopPropagation() instead. +UseOfGetBoxObjectForWarning=Use of getBoxObjectFor() is deprecated. Try to use element.getBoundingClientRect() if possible. UnexpectedCanvasVariantStyle=canvas: an attempt to set strokeStyle or fillStyle to a value that is neither a string, a CanvasGradient, or a CanvasPattern was ignored. EmptyGetElementByIdParam=Empty string passed to getElementById().