From 104eb64087e3f0452bbd9603951357e46ba98caa Mon Sep 17 00:00:00 2001 From: "peterv%propagandism.org" Date: Wed, 22 Nov 2006 18:35:05 +0000 Subject: [PATCH] Fix for bug 47903 (WRONG_DOCUMENT_ERR not being thrown). r=sicking, sr=bz. git-svn-id: svn://10.0.0.236/trunk@215687 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsContentUtils.h | 17 --- mozilla/content/base/public/nsINode.h | 17 +++ mozilla/content/base/src/nsContentUtils.cpp | 43 ------- .../content/base/src/nsDOMAttributeMap.cpp | 7 +- .../content/base/src/nsDOMDocumentType.cpp | 59 ++++++++++ mozilla/content/base/src/nsDOMDocumentType.h | 4 + mozilla/content/base/src/nsDocument.cpp | 24 +--- .../content/base/src/nsGenericDOMDataNode.cpp | 48 +------- mozilla/content/base/src/nsGenericElement.cpp | 107 ++++++------------ mozilla/content/base/src/nsGenericElement.h | 13 --- mozilla/content/base/src/nsNodeUtils.cpp | 50 ++++++-- .../html/document/src/nsHTMLContentSink.cpp | 22 ++-- .../content/xul/content/src/nsXULElement.cpp | 54 +-------- 13 files changed, 174 insertions(+), 291 deletions(-) diff --git a/mozilla/content/base/public/nsContentUtils.h b/mozilla/content/base/public/nsContentUtils.h index d2e32d009a9..fe746f756bc 100644 --- a/mozilla/content/base/public/nsContentUtils.h +++ b/mozilla/content/base/public/nsContentUtils.h @@ -840,23 +840,6 @@ public: nsIDOMUserDataHandler *aHandler, nsIVariant **aResult); - /** - * Call the UserDataHandler associated with aKey on node aNode. - * Should only be used to implement the DOM Level 3 UserData API. - * - * @param aDocument the document that contains the property table for aNode - * @param aOperation the type of operation that is being performed on the - * node. @see nsIDOMUserDataHandler - * @param aNode canonical nsINode pointer of the node to call the - * UserDataHandler for - * @param aSource the node that aOperation is being performed on, or null if - * the operation is a deletion - * @param aDest the newly created node if any, or null - */ - static void CallUserDataHandler(nsIDocument *aDocument, PRUint16 aOperation, - const nsINode *aNode, nsIDOMNode *aSource, - nsIDOMNode *aDest); - /** * Creates a DocumentFragment from text using a context node to resolve * namespaces. diff --git a/mozilla/content/base/public/nsINode.h b/mozilla/content/base/public/nsINode.h index 7797c60380c..ed643950e33 100644 --- a/mozilla/content/base/public/nsINode.h +++ b/mozilla/content/base/public/nsINode.h @@ -550,6 +550,23 @@ public: */ virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const = 0; + /** + * Checks if a node has the same ownerDocument as this one. Note that this + * actually compares nodeinfo managers because nodes always have one, even + * when they don't have an ownerDocument. If this function returns PR_TRUE + * it doesn't mean that the nodes actually have an ownerDocument. + * + * @param aOther Other node to check + * @return Whether the owner documents of this node and of aOther are the + * same. + */ + PRBool HasSameOwnerDoc(nsINode *aOther) + { + // We compare nodeinfo managers because nodes always have one, even when + // they don't have an ownerDocument. + return mNodeInfo->NodeInfoManager() == aOther->mNodeInfo->NodeInfoManager(); + } + // This class can be extended by subclasses that wish to store more // information in the slots. class nsSlots diff --git a/mozilla/content/base/src/nsContentUtils.cpp b/mozilla/content/base/src/nsContentUtils.cpp index a7a02e74491..6c7813068a7 100644 --- a/mozilla/content/base/src/nsContentUtils.cpp +++ b/mozilla/content/base/src/nsContentUtils.cpp @@ -3085,49 +3085,6 @@ nsContentUtils::SetUserData(nsINode *aNode, nsIAtom *aKey, return NS_OK; } -struct nsHandlerData -{ - PRUint16 mOperation; - nsIDOMNode *mSource; - nsIDOMNode *mDest; -}; - -static void -CallHandler(void *aObject, nsIAtom *aKey, void *aHandler, void *aData) -{ - nsHandlerData *handlerData = NS_STATIC_CAST(nsHandlerData*, aData); - nsCOMPtr handler = - NS_STATIC_CAST(nsIDOMUserDataHandler*, aHandler); - - nsINode *node = NS_STATIC_CAST(nsINode*, aObject); - nsCOMPtr data = - NS_STATIC_CAST(nsIVariant*, node->GetProperty(DOM_USER_DATA, aKey)); - NS_ASSERTION(data, "Handler without data?"); - - nsAutoString key; - aKey->ToString(key); - handler->Handle(handlerData->mOperation, key, data, handlerData->mSource, - handlerData->mDest); -} - -/* static */ -void -nsContentUtils::CallUserDataHandler(nsIDocument *aDocument, PRUint16 aOperation, - const nsINode *aNode, nsIDOMNode *aSource, - nsIDOMNode *aDest) -{ -#ifdef DEBUG - if (aOperation != nsIDOMUserDataHandler::NODE_DELETED) { - nsCOMPtr node = do_QueryInterface(NS_CONST_CAST(nsINode*, aNode)); - NS_ASSERTION(node == aNode, "Use canonical nsINode pointer!"); - } -#endif - - nsHandlerData handlerData = { aOperation, aSource, aDest }; - aDocument->PropertyTable()->Enumerate(aNode, DOM_USER_DATA_HANDLER, - CallHandler, &handlerData); -} - /* static */ nsresult nsContentUtils::CreateContextualFragment(nsIDOMNode* aContextNode, diff --git a/mozilla/content/base/src/nsDOMAttributeMap.cpp b/mozilla/content/base/src/nsDOMAttributeMap.cpp index 7ee35267bae..a40cce4f276 100644 --- a/mozilla/content/base/src/nsDOMAttributeMap.cpp +++ b/mozilla/content/base/src/nsDOMAttributeMap.cpp @@ -248,11 +248,8 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMNode *aNode, return NS_OK; } - // update nodeinfo if needed - nsIDocument* myDoc = mContent->GetOwnerDoc(); - if (myDoc && myDoc != iAttribute->GetOwnerDoc()) { - rv = iAttribute->SetOwnerDocument(myDoc); - NS_ENSURE_SUCCESS(rv, rv); + if (!mContent->HasSameOwnerDoc(iAttribute)) { + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; } // Get nodeinfo and preexisting attribute (if it exists) diff --git a/mozilla/content/base/src/nsDOMDocumentType.cpp b/mozilla/content/base/src/nsDOMDocumentType.cpp index c8e15d2e067..52fad89585c 100644 --- a/mozilla/content/base/src/nsDOMDocumentType.cpp +++ b/mozilla/content/base/src/nsDOMDocumentType.cpp @@ -50,6 +50,8 @@ #include "nsNodeInfoManager.h" #include "nsLayoutAtoms.h" #include "nsIDocument.h" +#include "nsIXPConnect.h" +#include "nsIDOMDocument.h" nsresult NS_NewDOMDocumentType(nsIDOMDocumentType** aDocType, @@ -237,3 +239,60 @@ nsDOMDocumentType::CloneDataNode(nsINodeInfo *aNodeInfo, PRBool aCloneText) cons return new nsDOMDocumentType(aNodeInfo, mName, mEntities, mNotations, mPublicId, mSystemId, mInternalSubset); } + +nsresult +nsDOMDocumentType::BindToTree(nsIDocument *aDocument, nsIContent *aParent, + nsIContent *aBindingParent, + PRBool aCompileEventHandlers) +{ + if (!HasSameOwnerDoc(NODE_FROM(aParent, aDocument))) { + NS_ASSERTION(!GetOwnerDoc(), "Need to adopt or import first!"); + + // DocumentType nodes are the only nodes that can have a null ownerDocument + // according to the DOM spec, so we need to give them a new nodeinfo in that + // case. + // XXX We may want to move this to nsDOMImplementation::CreateDocument if + // we want to rely on the nodeinfo and wrappers being right before + // getting into doReplaceOrInsertBefore or doInsertChildAt. That would + // break inserting DOMDocumentType nodes through other DOM methods + // though. + nsNodeInfoManager *nimgr = aParent ? + aParent->NodeInfo()->NodeInfoManager() : + aDocument->NodeInfoManager(); + nsCOMPtr newNodeInfo; + nsresult rv = nimgr->GetNodeInfo(mNodeInfo->NameAtom(), + mNodeInfo->GetPrefixAtom(), + mNodeInfo->NamespaceID(), + getter_AddRefs(newNodeInfo)); + NS_ENSURE_SUCCESS(rv, rv); + + mNodeInfo.swap(newNodeInfo); + + nsCOMPtr oldOwnerDoc = + do_QueryInterface(nsContentUtils::GetDocumentFromContext()); + nsIDocument *newOwnerDoc = nimgr->GetDocument(); + if (oldOwnerDoc && newOwnerDoc) { + nsIXPConnect *xpc = nsContentUtils::XPConnect(); + + JSContext *cx = nsnull; + JSObject *oldScope = nsnull, *newScope = nsnull; + rv = nsContentUtils::GetContextAndScopes(oldOwnerDoc, newOwnerDoc, &cx, + &oldScope, &newScope); + if (cx && xpc) { + nsISupports *node = NS_ISUPPORTS_CAST(nsIContent*, this); + nsCOMPtr oldWrapper; + rv = xpc->ReparentWrappedNativeIfFound(cx, oldScope, newScope, node, + getter_AddRefs(oldWrapper)); + } + + if (NS_FAILED(rv)) { + mNodeInfo.swap(newNodeInfo); + + return rv; + } + } + } + + return nsGenericDOMDataNode::BindToTree(aDocument, aParent, aBindingParent, + aCompileEventHandlers); +} diff --git a/mozilla/content/base/src/nsDOMDocumentType.h b/mozilla/content/base/src/nsDOMDocumentType.h index 86b3fd8b817..5bbd59f680d 100644 --- a/mozilla/content/base/src/nsDOMDocumentType.h +++ b/mozilla/content/base/src/nsDOMDocumentType.h @@ -79,6 +79,10 @@ public: // nsIContent overrides virtual PRBool IsNodeOfType(PRUint32 aFlags) const; virtual const nsTextFragment* GetText(); + virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent, + nsIContent *aBindingParent, + PRBool aCompileEventHandlers); + protected: nsCOMPtr mName; diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index 13bffaea38f..572787e5ed5 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -4069,29 +4069,7 @@ nsDocument::RenameNode(nsIDOMNode *aNode, const nsAString& qualifiedName, nsIDOMNode **aReturn) { - if (!aNode) { - // not an element or attribute - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; - } - - PRUint16 nodeType; - aNode->GetNodeType(&nodeType); - if (nodeType == nsIDOMNode::ELEMENT_NODE || - nodeType == nsIDOMNode::ATTRIBUTE_NODE) { - // XXXcaa Write me - Coming soon to a document near you! - return NS_ERROR_NOT_IMPLEMENTED; - } - -// if (NS_SUCCEEDED(rv)) { -// nsCOMPtr node = do_QueryInterface(aNode); -// if (node->HasProperties()) { -// nsContentUtils::CallUserDataHandler(this, -// nsIDOMUserDataHandler::NODE_RENAMED, -// node, aNode, *aReturn); -// } -// } - - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/mozilla/content/base/src/nsGenericDOMDataNode.cpp b/mozilla/content/base/src/nsGenericDOMDataNode.cpp index 88c4a798850..bc90f56fb7e 100644 --- a/mozilla/content/base/src/nsGenericDOMDataNode.cpp +++ b/mozilla/content/base/src/nsGenericDOMDataNode.cpp @@ -565,6 +565,8 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent, PRBool aCompileEventHandlers) { NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!"); + NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)), + "Must have the same owner document"); // XXXbz XUL elements are confused about their current doc when they're // cloned, so we don't assert if aParent is a XUL element and aDocument is // null, even if aParent->GetCurrentDoc() is non-null @@ -607,11 +609,6 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent, mParentPtrBits = NS_REINTERPRET_CAST(PtrBits, aDocument); } - nsresult rv = NS_OK; - nsCOMPtr oldOwnerDocument = GetOwnerDoc(); - nsIDocument *newOwnerDocument; - nsNodeInfoManager* nodeInfoManager; - // XXXbz sXBL/XBL2 issue! // Set document @@ -621,47 +618,6 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent, if (mText.IsBidi()) { aDocument->SetBidiEnabled(PR_TRUE); } - - newOwnerDocument = aDocument; - nodeInfoManager = newOwnerDocument->NodeInfoManager(); - } else { - newOwnerDocument = aParent->GetOwnerDoc(); - nodeInfoManager = aParent->NodeInfo()->NodeInfoManager(); - } - - if (mNodeInfo->NodeInfoManager() != nodeInfoManager) { - nsCOMPtr newNodeInfo; - // optimize common cases - nsIAtom* name = mNodeInfo->NameAtom(); - if (name == nsLayoutAtoms::textTagName) { - newNodeInfo = nodeInfoManager->GetTextNodeInfo(); - NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY); - } - else if (name == nsLayoutAtoms::commentTagName) { - newNodeInfo = nodeInfoManager->GetCommentNodeInfo(); - NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY); - } - else { - rv = nodeInfoManager->GetNodeInfo(name, - mNodeInfo->GetPrefixAtom(), - mNodeInfo->NamespaceID(), - getter_AddRefs(newNodeInfo)); - NS_ENSURE_SUCCESS(rv, rv); - } - mNodeInfo.swap(newNodeInfo); - } - - if (oldOwnerDocument && oldOwnerDocument != newOwnerDocument && - HasProperties()) { - nsPropertyTable *oldTable = oldOwnerDocument->PropertyTable(); - if (newOwnerDocument) { - nsPropertyTable *newTable = newOwnerDocument->PropertyTable(); - - oldTable->TransferOrDeleteAllPropertiesFor(this, newTable); - } - else { - oldTable->DeleteAllPropertiesFor(this); - } } NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document"); diff --git a/mozilla/content/base/src/nsGenericElement.cpp b/mozilla/content/base/src/nsGenericElement.cpp index 3dbdaf0fee9..478a7755eeb 100644 --- a/mozilla/content/base/src/nsGenericElement.cpp +++ b/mozilla/content/base/src/nsGenericElement.cpp @@ -1762,6 +1762,8 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, PRBool aCompileEventHandlers) { NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!"); + NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)), + "Must have the same owner document"); // XXXbz XUL elements are confused about their current doc when they're // cloned, so we don't assert if aParent is a XUL element and aDocument is // null, even if aParent->GetCurrentDoc() is non-null @@ -1805,12 +1807,6 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, mParentPtrBits = NS_REINTERPRET_CAST(PtrBits, aDocument); } - nsresult rv; - - nsCOMPtr oldOwnerDocument = GetOwnerDoc(); - nsIDocument *newOwnerDocument; - nsNodeInfoManager* nodeInfoManager; - // XXXbz sXBL/XBL2 issue! // Finally, set the document @@ -1826,51 +1822,10 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // Being added to a document. mParentPtrBits |= PARENT_BIT_INDOCUMENT; - - newOwnerDocument = aDocument; - nodeInfoManager = newOwnerDocument->NodeInfoManager(); - } else { - newOwnerDocument = aParent->GetOwnerDoc(); - nodeInfoManager = aParent->NodeInfo()->NodeInfoManager(); - } - - // Handle a change in our owner document. - - if (mNodeInfo->NodeInfoManager() != nodeInfoManager) { - nsCOMPtr newNodeInfo; - rv = nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(), - mNodeInfo->GetPrefixAtom(), - mNodeInfo->NamespaceID(), - getter_AddRefs(newNodeInfo)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(newNodeInfo, "GetNodeInfo lies"); - mNodeInfo.swap(newNodeInfo); - } - - if (oldOwnerDocument != newOwnerDocument) { - if (oldOwnerDocument && HasProperties()) { - nsPropertyTable *oldTable = oldOwnerDocument->PropertyTable(); - if (newOwnerDocument) { - nsPropertyTable *newTable = newOwnerDocument->PropertyTable(); - - oldTable->TransferOrDeleteAllPropertiesFor(this, newTable); - } - else { - oldTable->DeleteAllPropertiesFor(this); - } - } - - if (newOwnerDocument) { - // set a new nodeinfo on attribute nodes - nsDOMSlots *slots = GetExistingDOMSlots(); - if (slots && slots->mAttributeMap) { - rv = slots->mAttributeMap->SetOwnerDocument(newOwnerDocument); - NS_ENSURE_SUCCESS(rv, rv); - } - } } // Now recurse into our kids + nsresult rv; PRUint32 i; for (i = 0; i < GetChildCount(); ++i) { // The child can remove itself from the parent in BindToTree. @@ -2314,6 +2269,27 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument, "Incorrect aDocument"); + nsresult rv; + nsINode* container = NODE_FROM(aParent, aDocument); + if (!container->HasSameOwnerDoc(aKid)) { + if (aKid->GetOwnerDoc()) { + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; + } + + nsCOMPtr kid = do_QueryInterface(aKid, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint16 nodeType = 0; + rv = kid->GetNodeType(&nodeType); + NS_ENSURE_SUCCESS(rv, rv); + + // DocumentType nodes are the only nodes that can have a null ownerDocument + // according to the DOM spec, and we need to allow inserting them. + if (nodeType != nsIDOMNode::DOCUMENT_TYPE_NODE) { + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; + } + } + PRUint32 childCount = aChildArray.ChildCount(); NS_ENSURE_TRUE(aIndex <= childCount, NS_ERROR_ILLEGAL_VALUE); @@ -2323,7 +2299,7 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify); - nsresult rv = aChildArray.InsertChildAt(aKid, aIndex); + rv = aChildArray.InsertChildAt(aKid, aIndex); NS_ENSURE_SUCCESS(rv, rv); rv = aKid->BindToTree(aDocument, aParent, nsnull, PR_TRUE); @@ -2341,7 +2317,6 @@ nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, // really need to stop running them while we're in the middle of modifying // the DOM.... - nsINode* container = NODE_FROM(aParent, aDocument); if (aNotify && aKid->GetNodeParent() == container) { // Note that we always want to call ContentInserted when things are added // as kids to documents @@ -2777,24 +2752,16 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace, return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; } - nsIDocument* old_doc = newContent->GetOwnerDoc(); + if (!container->HasSameOwnerDoc(newContent)) { + // DocumentType nodes are the only nodes that can have a null ownerDocument + // according to the DOM spec, and we need to allow inserting them. + if (nodeType != nsIDOMNode::DOCUMENT_TYPE_NODE || + newContent->GetOwnerDoc()) { + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; + } - // XXXbz The document code and content code have two totally different - // security checks here. Why? Because I'm afraid to change such things this - // close to 1.8. But which should we do here, really? Or both? For example - // what should a caller with UniversalBrowserRead/Write/whatever be able to - // do, exactly? Do we need to be more careful with documents because random - // callers _can_ get access to them? That might be.... - if (old_doc && old_doc != container->GetOwnerDoc()) { - if (aParent) { - if (!nsContentUtils::CanCallerAccess(aNewChild)) { - return NS_ERROR_DOM_SECURITY_ERR; - } - } else { - nsCOMPtr doc(do_QueryInterface(aDocument)); - if (NS_FAILED(nsContentUtils::CheckSameOrigin(doc, aNewChild))) { - return NS_ERROR_DOM_SECURITY_ERR; - } + if (!nsContentUtils::CanCallerAccess(aNewChild)) { + return NS_ERROR_DOM_SECURITY_ERR; } } @@ -2947,8 +2914,8 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace, } if (newContent->GetNodeParent() || - !IsAllowedAsChild(newContent, nodeType, aParent, aDocument, PR_FALSE, - refContent)) { + !IsAllowedAsChild(newContent, nodeType, aParent, aDocument, + PR_FALSE, refContent)) { return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR; } } @@ -2957,7 +2924,7 @@ nsGenericElement::doReplaceOrInsertBefore(PRBool aReplace, if (!newContentIsXUL) { nsContentUtils::ReparentContentWrapper(newContent, aParent, container->GetOwnerDoc(), - old_doc); + container->GetOwnerDoc()); } res = container->InsertChildAt(newContent, insPos, PR_TRUE); diff --git a/mozilla/content/base/src/nsGenericElement.h b/mozilla/content/base/src/nsGenericElement.h index c74c1deccec..fa577686c3c 100644 --- a/mozilla/content/base/src/nsGenericElement.h +++ b/mozilla/content/base/src/nsGenericElement.h @@ -585,19 +585,6 @@ public: nsresult JoinTextNodes(nsIContent* aFirst, nsIContent* aSecond); - /** - * Set .document in the immediate children of said content (but not in - * content itself). SetDocument() in the children will recursively call - * this. - * - * @param aContent the content to get the children of - * @param aDocument the document to set - * @param aCompileEventHandlers whether to initialize the event handlers in - * the document (used by nsXULElement) - */ - static void SetDocumentInChildrenOf(nsIContent* aContent, - nsIDocument* aDocument, PRBool aCompileEventHandlers); - /** * Check whether a spec feature/version is supported. * @param aObject the object, which should support the feature, diff --git a/mozilla/content/base/src/nsNodeUtils.cpp b/mozilla/content/base/src/nsNodeUtils.cpp index 653514a7ed8..92ba9385450 100755 --- a/mozilla/content/base/src/nsNodeUtils.cpp +++ b/mozilla/content/base/src/nsNodeUtils.cpp @@ -39,7 +39,6 @@ #include "nsContentUtils.h" #include "nsINode.h" #include "nsIContent.h" -#include "nsTArray.h" #include "nsIMutationObserver.h" #include "nsIDocument.h" #include "nsIDOMUserDataHandler.h" @@ -157,6 +156,30 @@ nsNodeUtils::ContentRemoved(nsINode* aContainer, (document, container, aChild, aIndexInContainer)); } +struct nsHandlerData +{ + PRUint16 mOperation; + nsCOMPtr mSource, mDest; +}; + +static void +CallHandler(void *aObject, nsIAtom *aKey, void *aHandler, void *aData) +{ + nsHandlerData *handlerData = NS_STATIC_CAST(nsHandlerData*, aData); + nsCOMPtr handler = + NS_STATIC_CAST(nsIDOMUserDataHandler*, aHandler); + + nsINode *node = NS_STATIC_CAST(nsINode*, aObject); + nsCOMPtr data = + NS_STATIC_CAST(nsIVariant*, node->GetProperty(DOM_USER_DATA, aKey)); + NS_ASSERTION(data, "Handler without data?"); + + nsAutoString key; + aKey->ToString(key); + handler->Handle(handlerData->mOperation, key, data, handlerData->mSource, + handlerData->mDest); +} + void nsNodeUtils::LastRelease(nsINode* aNode, PRBool aDelete) { @@ -178,10 +201,13 @@ nsNodeUtils::LastRelease(nsINode* aNode, PRBool aDelete) if (aNode->HasProperties()) { nsIDocument* document = aNode->GetOwnerDoc(); if (document) { - nsContentUtils::CallUserDataHandler(document, - nsIDOMUserDataHandler::NODE_DELETED, - aNode, nsnull, nsnull); - document->PropertyTable()->DeleteAllPropertiesFor(aNode); + nsHandlerData handlerData; + handlerData.mOperation = nsIDOMUserDataHandler::NODE_DELETED; + + nsPropertyTable *table = document->PropertyTable(); + + table->Enumerate(aNode, DOM_USER_DATA_HANDLER, CallHandler, &handlerData); + table->DeleteAllPropertiesFor(aNode); } aNode->UnsetFlags(NODE_HAS_PROPERTIES); } @@ -219,26 +245,30 @@ nsNodeUtils::CallUserDataHandlers(nsCOMArray &aNodesWithProperties, "Expected aNodesWithProperties to contain original and " "cloned nodes."); + nsPropertyTable *table = aOwnerDocument->PropertyTable(); + // Keep the document alive, just in case one of the handlers causes it to go // away. nsCOMPtr ownerDoc = aOwnerDocument; + nsHandlerData handlerData; + handlerData.mOperation = aOperation; + PRUint32 i, count = aNodesWithProperties.Count(); for (i = 0; i < count; ++i) { nsINode *nodeWithProperties = aNodesWithProperties[i]; nsresult rv; - nsCOMPtr source = do_QueryInterface(nodeWithProperties, &rv); + handlerData.mSource = do_QueryInterface(nodeWithProperties, &rv); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr dest; if (aCloned) { - dest = do_QueryInterface(aNodesWithProperties[++i], &rv); + handlerData.mDest = do_QueryInterface(aNodesWithProperties[++i], &rv); NS_ENSURE_SUCCESS(rv, rv); } - nsContentUtils::CallUserDataHandler(aOwnerDocument, aOperation, - nodeWithProperties, source, dest); + table->Enumerate(nodeWithProperties, DOM_USER_DATA_HANDLER, CallHandler, + &handlerData); } return NS_OK; diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index c3523e26bd0..997d7702ef4 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -3153,25 +3153,21 @@ HTMLContentSink::AddDocTypeDecl(const nsIParserNode& aNode) nsCOMPtr doc(do_QueryInterface(mHTMLDocument)); doc->GetDoctype(getter_AddRefs(oldDocType)); - nsCOMPtr domImpl; - - rv = doc->GetImplementation(getter_AddRefs(domImpl)); - - if (NS_FAILED(rv) || !domImpl) { - return rv; - } - if (name.IsEmpty()) { name.AssignLiteral("HTML"); } - rv = domImpl->CreateDocumentType(name, publicId, systemId, - getter_AddRefs(docType)); - - if (NS_FAILED(rv) || !docType) { - return rv; + nsCOMPtr nameAtom = do_GetAtom(name); + if (!nameAtom) { + return NS_ERROR_OUT_OF_MEMORY; } + rv = NS_NewDOMDocumentType(getter_AddRefs(docType), + mDocument->NodeInfoManager(), nsnull, + nameAtom, nsnull, nsnull, publicId, systemId, + EmptyString()); + NS_ENSURE_SUCCESS(rv, rv); + if (oldDocType) { // If we already have a doctype we replace the old one. nsCOMPtr tmpNode; diff --git a/mozilla/content/xul/content/src/nsXULElement.cpp b/mozilla/content/xul/content/src/nsXULElement.cpp index a06e1caa2c4..26661c35755 100644 --- a/mozilla/content/xul/content/src/nsXULElement.cpp +++ b/mozilla/content/xul/content/src/nsXULElement.cpp @@ -778,6 +778,8 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, PRBool aCompileEventHandlers) { NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!"); + NS_PRECONDITION(HasSameOwnerDoc(NODE_FROM(aParent, aDocument)), + "Must have the same owner document"); // XXXbz XUL elements are confused about their current doc when they're // cloned, so we don't assert if aParent is a XUL element and aDocument is // null, even if aParent->GetCurrentDoc() is non-null @@ -805,8 +807,6 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, aParent->GetBindingParent() == GetBindingParent()), "Already have a binding parent. Unbind first!"); - nsresult rv; - if (!aBindingParent && aParent) { aBindingParent = aParent->GetBindingParent(); } @@ -822,10 +822,6 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, mParentPtrBits = NS_REINTERPRET_CAST(PtrBits, aDocument); } - nsCOMPtr oldOwnerDocument = GetOwnerDoc(); - nsIDocument *newOwnerDocument; - nsNodeInfoManager* nodeInfoManager; - // XXXbz sXBL/XBL2 issue! // Finally, set the document @@ -843,54 +839,10 @@ nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, // Being added to a document. mParentPtrBits |= PARENT_BIT_INDOCUMENT; - - newOwnerDocument = aDocument; - nodeInfoManager = newOwnerDocument->NodeInfoManager(); - } else { - newOwnerDocument = aParent->GetOwnerDoc(); - nodeInfoManager = aParent->NodeInfo()->NodeInfoManager(); - } - - // Handle a change in our owner document. - - if (mNodeInfo->NodeInfoManager() != nodeInfoManager) { - nsCOMPtr newNodeInfo; - nsresult rv = - nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(), - mNodeInfo->GetPrefixAtom(), - mNodeInfo->NamespaceID(), - getter_AddRefs(newNodeInfo)); - NS_ENSURE_SUCCESS(rv, rv); - NS_ASSERTION(newNodeInfo, "GetNodeInfo lies"); - mNodeInfo.swap(newNodeInfo); - } - - if (oldOwnerDocument != newOwnerDocument) { - if (oldOwnerDocument && HasProperties()) { - nsPropertyTable *oldTable = oldOwnerDocument->PropertyTable(); - if (newOwnerDocument) { - nsPropertyTable *newTable = newOwnerDocument->PropertyTable(); - - oldTable->TransferOrDeleteAllPropertiesFor(this, newTable); - } - else { - oldTable->DeleteAllPropertiesFor(this); - } - } - - if (newOwnerDocument) { - // set a new nodeinfo on attribute nodes - nsDOMSlots *slots = GetExistingDOMSlots(); - if (slots && slots->mAttributeMap) { - rv = slots->mAttributeMap->SetOwnerDocument(newOwnerDocument); - NS_ENSURE_SUCCESS(rv, rv); - } - - RecompileScriptEventListeners(); - } } // Now recurse into our kids + nsresult rv; PRUint32 i; for (i = 0; i < GetChildCount(); ++i) { // The child can remove itself from the parent in BindToTree.