Bugs 20677, 23905. Change nsXULElement to implement nsIContent like nsGenericElement and nsGenericHTMLElement. Specifically, do 'shallow' SetDocument() calls in AppendChildTo(), InsertChildAt() and ReplaceChildAt() methods. Change nsXULDocument to leave newly create element's mDocument as null (so 'null mDocument' means 'this element is not currently in the document'. Fix callers to ensure that a deep SetDocument() is made where necessary. r=hyatt

This commit is contained in:
waterson%netscape.com 2000-02-01 22:57:36 +00:00
Родитель 194a2b8075
Коммит a26daa2f0d
9 изменённых файлов: 145 добавлений и 154 удалений

Просмотреть файл

@ -916,6 +916,12 @@ nsXULElement::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMN
rv = InsertChildAt(newcontent, pos, PR_TRUE); rv = InsertChildAt(newcontent, pos, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert aNewChild"); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert aNewChild");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// Because InsertChildAt() only does a "shallow"
// SetDocument(), we need to ensure that a "deep" one is
// done now...
rv = newcontent->SetDocument(mDocument, PR_TRUE);
if (NS_FAILED(rv)) return rv;
} }
// XXX Hmm. There's a case here that we handle ambiguously, I // XXX Hmm. There's a case here that we handle ambiguously, I
@ -927,6 +933,12 @@ nsXULElement::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMN
rv = AppendChildTo(newcontent, PR_TRUE); rv = AppendChildTo(newcontent, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to append a aNewChild"); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to append a aNewChild");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// Because AppendChildTo() only does a "shallow"
// SetDocument(), we need to ensure that a "deep" one is done
// now...
rv = newcontent->SetDocument(mDocument, PR_TRUE);
if (NS_FAILED(rv)) return rv;
} }
NS_ADDREF(aNewChild); NS_ADDREF(aNewChild);
@ -963,6 +975,12 @@ nsXULElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMN
if (newelement) { if (newelement) {
rv = ReplaceChildAt(newelement, pos, PR_TRUE); rv = ReplaceChildAt(newelement, pos, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to replace old child"); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to replace old child");
// Because ReplaceChildAt() only does a "shallow"
// SetDocument(), we need to ensure that a "deep" one
// is done now...
rv = newelement->SetDocument(mDocument, PR_TRUE);
if (NS_FAILED(rv)) return rv;
} }
} }
} }
@ -1856,40 +1874,39 @@ nsXULElement::GetDocument(nsIDocument*& aResult) const
NS_IMETHODIMP NS_IMETHODIMP
nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep) nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep)
{ {
if (aDocument == mDocument)
return NS_OK;
nsresult rv; nsresult rv;
nsCOMPtr<nsIXULDocument> rdfDoc; if (aDocument != mDocument) {
if (mDocument) { nsCOMPtr<nsIXULDocument> rdfDoc;
// Release the named reference to the script object so it can if (mDocument) {
// be garbage collected. // Release the named reference to the script object so it can
if (mScriptObject) { // be garbage collected.
nsCOMPtr<nsIScriptGlobalObject> global; if (mScriptObject) {
mDocument->GetScriptGlobalObject(getter_AddRefs(global)); nsCOMPtr<nsIScriptGlobalObject> global;
if (global) { mDocument->GetScriptGlobalObject(getter_AddRefs(global));
nsCOMPtr<nsIScriptContext> context; if (global) {
global->GetContext(getter_AddRefs(context)); nsCOMPtr<nsIScriptContext> context;
if (context) { global->GetContext(getter_AddRefs(context));
context->RemoveReference((void*) &mScriptObject, mScriptObject); if (context) {
context->RemoveReference((void*) &mScriptObject, mScriptObject);
}
} }
} }
} }
}
mDocument = aDocument; // not refcounted mDocument = aDocument; // not refcounted
if (mDocument) { if (mDocument) {
// Add a named reference to the script object. // Add a named reference to the script object.
if (mScriptObject) { if (mScriptObject) {
nsCOMPtr<nsIScriptGlobalObject> global; nsCOMPtr<nsIScriptGlobalObject> global;
mDocument->GetScriptGlobalObject(getter_AddRefs(global)); mDocument->GetScriptGlobalObject(getter_AddRefs(global));
if (global) { if (global) {
nsCOMPtr<nsIScriptContext> context; nsCOMPtr<nsIScriptContext> context;
global->GetContext(getter_AddRefs(context)); global->GetContext(getter_AddRefs(context));
if (context) { if (context) {
context->AddNamedReference((void*) &mScriptObject, mScriptObject, "nsXULElement::mScriptObject"); context->AddNamedReference((void*) &mScriptObject, mScriptObject, "nsXULElement::mScriptObject");
}
} }
} }
} }
@ -1916,6 +1933,7 @@ nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep)
child->SetDocument(aDocument, aDeep); child->SetDocument(aDocument, aDeep);
} }
} }
return NS_OK; return NS_OK;
} }
@ -2010,10 +2028,10 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
//nsRange::OwnerChildInserted(this, aIndex); //nsRange::OwnerChildInserted(this, aIndex);
//XXXwaterson this should be shallow // N.B. that this is "shallow"!
aKid->SetDocument(mDocument, PR_TRUE); aKid->SetDocument(mDocument, PR_FALSE);
if (aNotify && ElementIsInDocument()) { if (aNotify && mDocument) {
mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex); mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex);
} }
} }
@ -2052,18 +2070,17 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
//nsRange::OwnerChildReplaced(this, aIndex, oldKid); //nsRange::OwnerChildReplaced(this, aIndex, oldKid);
//XXXwaterson this should be shallow // N.B. that we only do a "shallow" SetDocument()
aKid->SetDocument(mDocument, PR_TRUE); // here. Callers beware!
aKid->SetDocument(mDocument, PR_FALSE);
if (aNotify && ElementIsInDocument()) { if (aNotify && mDocument) {
mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex); mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex);
} }
#if 0 //XXXwaterson put this in eventually.
// This will cause the script object to be unrooted for each // This will cause the script object to be unrooted for each
// element in the subtree. // element in the subtree.
oldKid->SetDocument(nsnull, PR_TRUE); oldKid->SetDocument(nsnull, PR_TRUE);
#endif
// We've got no mo' parent. // We've got no mo' parent.
oldKid->SetParent(nsnull); oldKid->SetParent(nsnull);
@ -2090,10 +2107,10 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
// ranges don't need adjustment since new child is at end of list // ranges don't need adjustment since new child is at end of list
//XXXwaterson this should be shallow // N.B. that this is only "shallow". Callers beware!
aKid->SetDocument(mDocument, PR_TRUE); aKid->SetDocument(mDocument, PR_FALSE);
if (aNotify && ElementIsInDocument()) { if (aNotify && mDocument) {
PRUint32 cnt; PRUint32 cnt;
rv = mChildren->Count(&cnt); rv = mChildren->Count(&cnt);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
@ -2194,15 +2211,13 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
nsIDocument* doc = mDocument; nsIDocument* doc = mDocument;
PRBool removeOk = mChildren->RemoveElementAt(aIndex); PRBool removeOk = mChildren->RemoveElementAt(aIndex);
//nsRange::OwnerChildRemoved(this, aIndex, oldKid); //nsRange::OwnerChildRemoved(this, aIndex, oldKid);
if (aNotify && removeOk && ElementIsInDocument()) { if (aNotify && removeOk && mDocument) {
doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex); doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex);
} }
#if 0 //XXXwaterson put this in eventually
// This will cause the script object to be unrooted for each // This will cause the script object to be unrooted for each
// element in the subtree. // element in the subtree.
oldKid->SetDocument(nsnull, PR_TRUE); oldKid->SetDocument(nsnull, PR_TRUE);
#endif
// We've got no mo' parent. // We've got no mo' parent.
oldKid->SetParent(nsnull); oldKid->SetParent(nsnull);
@ -3248,37 +3263,6 @@ nsXULElement::ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsString
} }
PRBool
nsXULElement::ElementIsInDocument()
{
// Check to see if the element is really _in_ the document; that
// is, that it actually is in the tree rooted at the document's
// root content.
if (! mDocument)
return PR_FALSE;
nsresult rv;
nsCOMPtr<nsIContent> root = dont_AddRef( mDocument->GetRootContent() );
if (! root)
return PR_FALSE;
// Hack to get off scc's evil-use-of-do_QueryInterface() radar.
nsIStyledContent* p = NS_STATIC_CAST(nsIStyledContent*, this);
nsCOMPtr<nsIContent> node = do_QueryInterface(p);
while (node) {
if (node == root)
return PR_TRUE;
nsCOMPtr<nsIContent> oldNode = node;
rv = oldNode->GetParent(*getter_AddRefs(node));
if (NS_FAILED(rv)) return PR_FALSE;
}
return PR_FALSE;
}
nsresult nsresult
nsXULElement::ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent) nsXULElement::ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent)
{ {

Просмотреть файл

@ -508,8 +508,6 @@ protected:
nsresult ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsString& attrName); nsresult ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsString& attrName);
PRBool ElementIsInDocument();
static nsresult static nsresult
ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent); ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent);

Просмотреть файл

@ -4001,9 +4001,6 @@ nsXULDocument::CreateElement(PRInt32 aNameSpaceID,
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
#if 1 // XXXwaterson remove this eventually
result->SetDocument(this, PR_FALSE);
#endif
result->SetContentID(mNextContentID++); result->SetContentID(mNextContentID++);
*aResult = result; *aResult = result;
@ -5668,6 +5665,17 @@ nsXULDocument::InsertElement(nsIContent* aParent, nsIContent* aChild)
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} }
// Both InsertChildAt() and AppendChildTo() only do a "shallow"
// SetDocument(); make sure that we do a "deep" one now...
nsCOMPtr<nsIDocument> doc;
rv = aParent->GetDocument(*getter_AddRefs(doc));
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(doc != nsnull, "merging into null document");
rv = aChild->SetDocument(doc, PR_TRUE);
if (NS_FAILED(rv)) return rv;
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -3900,6 +3900,7 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
// We have to make a box to hold everything. // We have to make a box to hold everything.
nsdoc->CreateElementWithNameSpace(nsAutoString("box"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("box"), xulNamespace, getter_AddRefs(node));
content = do_QueryInterface(node); content = do_QueryInterface(node);
content->SetDocument(doc, PR_FALSE);
anonymousItems->AppendElement(content); anonymousItems->AppendElement(content);
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("tree-icon"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("tree-icon"), PR_FALSE);
content->SetAttribute(kNameSpaceID_None, nsXULAtoms::flex, nsAutoString("1"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsXULAtoms::flex, nsAutoString("1"), PR_FALSE);
@ -3908,6 +3909,8 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
// Make the indentation. // Make the indentation.
nsdoc->CreateElementWithNameSpace(nsAutoString("treeindentation"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("treeindentation"), xulNamespace, getter_AddRefs(node));
content = do_QueryInterface(node);
content->SetDocument(doc, PR_FALSE);
boxElement->AppendChild(node, getter_AddRefs(dummy)); boxElement->AppendChild(node, getter_AddRefs(dummy));
nsCOMPtr<nsIContent> treeRow; nsCOMPtr<nsIContent> treeRow;
@ -3922,6 +3925,7 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
// Always make a twisty but disable it for non-containers. // Always make a twisty but disable it for non-containers.
nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node));
content = do_QueryInterface(node); content = do_QueryInterface(node);
content->SetDocument(doc, PR_FALSE);
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("twisty"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("twisty"), PR_FALSE);
if (container != "true") if (container != "true")
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, nsAutoString("true"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, nsAutoString("true"), PR_FALSE);
@ -3934,6 +3938,7 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node));
buttonContent = do_QueryInterface(node); buttonContent = do_QueryInterface(node);
buttonContent->SetDocument(doc, PR_FALSE);
buttonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, classDesc, PR_FALSE); buttonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, classDesc, PR_FALSE);
nsAutoString value; nsAutoString value;

Просмотреть файл

@ -3900,6 +3900,7 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
// We have to make a box to hold everything. // We have to make a box to hold everything.
nsdoc->CreateElementWithNameSpace(nsAutoString("box"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("box"), xulNamespace, getter_AddRefs(node));
content = do_QueryInterface(node); content = do_QueryInterface(node);
content->SetDocument(doc, PR_FALSE);
anonymousItems->AppendElement(content); anonymousItems->AppendElement(content);
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("tree-icon"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("tree-icon"), PR_FALSE);
content->SetAttribute(kNameSpaceID_None, nsXULAtoms::flex, nsAutoString("1"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsXULAtoms::flex, nsAutoString("1"), PR_FALSE);
@ -3908,6 +3909,8 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
// Make the indentation. // Make the indentation.
nsdoc->CreateElementWithNameSpace(nsAutoString("treeindentation"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("treeindentation"), xulNamespace, getter_AddRefs(node));
content = do_QueryInterface(node);
content->SetDocument(doc, PR_FALSE);
boxElement->AppendChild(node, getter_AddRefs(dummy)); boxElement->AppendChild(node, getter_AddRefs(dummy));
nsCOMPtr<nsIContent> treeRow; nsCOMPtr<nsIContent> treeRow;
@ -3922,6 +3925,7 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
// Always make a twisty but disable it for non-containers. // Always make a twisty but disable it for non-containers.
nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node));
content = do_QueryInterface(node); content = do_QueryInterface(node);
content->SetDocument(doc, PR_FALSE);
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("twisty"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, nsAutoString("twisty"), PR_FALSE);
if (container != "true") if (container != "true")
content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, nsAutoString("true"), PR_FALSE); content->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::disabled, nsAutoString("true"), PR_FALSE);
@ -3934,6 +3938,7 @@ nsCSSFrameConstructor::CreateAnonymousTreeCellFrames(nsIPresShell* aPresS
nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node)); nsdoc->CreateElementWithNameSpace(nsAutoString("titledbutton"), xulNamespace, getter_AddRefs(node));
buttonContent = do_QueryInterface(node); buttonContent = do_QueryInterface(node);
buttonContent->SetDocument(doc, PR_FALSE);
buttonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, classDesc, PR_FALSE); buttonContent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::kClass, classDesc, PR_FALSE);
nsAutoString value; nsAutoString value;

Просмотреть файл

@ -1653,6 +1653,7 @@ void nsTreeRowGroupFrame::CreateScrollbar(nsIPresContext* aPresContext)
document->CreateElement("scrollbar",getter_AddRefs(node)); document->CreateElement("scrollbar",getter_AddRefs(node));
nsCOMPtr<nsIContent> content = do_QueryInterface(node); nsCOMPtr<nsIContent> content = do_QueryInterface(node);
content->SetDocument(idocument, PR_FALSE);
content->SetParent(mContent); content->SetParent(mContent);
nsCOMPtr<nsIXULContent> xulContent = do_QueryInterface(content); nsCOMPtr<nsIXULContent> xulContent = do_QueryInterface(content);

Просмотреть файл

@ -4001,9 +4001,6 @@ nsXULDocument::CreateElement(PRInt32 aNameSpaceID,
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
#if 1 // XXXwaterson remove this eventually
result->SetDocument(this, PR_FALSE);
#endif
result->SetContentID(mNextContentID++); result->SetContentID(mNextContentID++);
*aResult = result; *aResult = result;
@ -5668,6 +5665,17 @@ nsXULDocument::InsertElement(nsIContent* aParent, nsIContent* aChild)
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} }
// Both InsertChildAt() and AppendChildTo() only do a "shallow"
// SetDocument(); make sure that we do a "deep" one now...
nsCOMPtr<nsIDocument> doc;
rv = aParent->GetDocument(*getter_AddRefs(doc));
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(doc != nsnull, "merging into null document");
rv = aChild->SetDocument(doc, PR_TRUE);
if (NS_FAILED(rv)) return rv;
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -916,6 +916,12 @@ nsXULElement::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMN
rv = InsertChildAt(newcontent, pos, PR_TRUE); rv = InsertChildAt(newcontent, pos, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert aNewChild"); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert aNewChild");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// Because InsertChildAt() only does a "shallow"
// SetDocument(), we need to ensure that a "deep" one is
// done now...
rv = newcontent->SetDocument(mDocument, PR_TRUE);
if (NS_FAILED(rv)) return rv;
} }
// XXX Hmm. There's a case here that we handle ambiguously, I // XXX Hmm. There's a case here that we handle ambiguously, I
@ -927,6 +933,12 @@ nsXULElement::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMN
rv = AppendChildTo(newcontent, PR_TRUE); rv = AppendChildTo(newcontent, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to append a aNewChild"); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to append a aNewChild");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// Because AppendChildTo() only does a "shallow"
// SetDocument(), we need to ensure that a "deep" one is done
// now...
rv = newcontent->SetDocument(mDocument, PR_TRUE);
if (NS_FAILED(rv)) return rv;
} }
NS_ADDREF(aNewChild); NS_ADDREF(aNewChild);
@ -963,6 +975,12 @@ nsXULElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMN
if (newelement) { if (newelement) {
rv = ReplaceChildAt(newelement, pos, PR_TRUE); rv = ReplaceChildAt(newelement, pos, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to replace old child"); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to replace old child");
// Because ReplaceChildAt() only does a "shallow"
// SetDocument(), we need to ensure that a "deep" one
// is done now...
rv = newelement->SetDocument(mDocument, PR_TRUE);
if (NS_FAILED(rv)) return rv;
} }
} }
} }
@ -1856,40 +1874,39 @@ nsXULElement::GetDocument(nsIDocument*& aResult) const
NS_IMETHODIMP NS_IMETHODIMP
nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep) nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep)
{ {
if (aDocument == mDocument)
return NS_OK;
nsresult rv; nsresult rv;
nsCOMPtr<nsIXULDocument> rdfDoc; if (aDocument != mDocument) {
if (mDocument) { nsCOMPtr<nsIXULDocument> rdfDoc;
// Release the named reference to the script object so it can if (mDocument) {
// be garbage collected. // Release the named reference to the script object so it can
if (mScriptObject) { // be garbage collected.
nsCOMPtr<nsIScriptGlobalObject> global; if (mScriptObject) {
mDocument->GetScriptGlobalObject(getter_AddRefs(global)); nsCOMPtr<nsIScriptGlobalObject> global;
if (global) { mDocument->GetScriptGlobalObject(getter_AddRefs(global));
nsCOMPtr<nsIScriptContext> context; if (global) {
global->GetContext(getter_AddRefs(context)); nsCOMPtr<nsIScriptContext> context;
if (context) { global->GetContext(getter_AddRefs(context));
context->RemoveReference((void*) &mScriptObject, mScriptObject); if (context) {
context->RemoveReference((void*) &mScriptObject, mScriptObject);
}
} }
} }
} }
}
mDocument = aDocument; // not refcounted mDocument = aDocument; // not refcounted
if (mDocument) { if (mDocument) {
// Add a named reference to the script object. // Add a named reference to the script object.
if (mScriptObject) { if (mScriptObject) {
nsCOMPtr<nsIScriptGlobalObject> global; nsCOMPtr<nsIScriptGlobalObject> global;
mDocument->GetScriptGlobalObject(getter_AddRefs(global)); mDocument->GetScriptGlobalObject(getter_AddRefs(global));
if (global) { if (global) {
nsCOMPtr<nsIScriptContext> context; nsCOMPtr<nsIScriptContext> context;
global->GetContext(getter_AddRefs(context)); global->GetContext(getter_AddRefs(context));
if (context) { if (context) {
context->AddNamedReference((void*) &mScriptObject, mScriptObject, "nsXULElement::mScriptObject"); context->AddNamedReference((void*) &mScriptObject, mScriptObject, "nsXULElement::mScriptObject");
}
} }
} }
} }
@ -1916,6 +1933,7 @@ nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep)
child->SetDocument(aDocument, aDeep); child->SetDocument(aDocument, aDeep);
} }
} }
return NS_OK; return NS_OK;
} }
@ -2010,10 +2028,10 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
//nsRange::OwnerChildInserted(this, aIndex); //nsRange::OwnerChildInserted(this, aIndex);
//XXXwaterson this should be shallow // N.B. that this is "shallow"!
aKid->SetDocument(mDocument, PR_TRUE); aKid->SetDocument(mDocument, PR_FALSE);
if (aNotify && ElementIsInDocument()) { if (aNotify && mDocument) {
mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex); mDocument->ContentInserted(NS_STATIC_CAST(nsIStyledContent*, this), aKid, aIndex);
} }
} }
@ -2052,18 +2070,17 @@ nsXULElement::ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify)
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
//nsRange::OwnerChildReplaced(this, aIndex, oldKid); //nsRange::OwnerChildReplaced(this, aIndex, oldKid);
//XXXwaterson this should be shallow // N.B. that we only do a "shallow" SetDocument()
aKid->SetDocument(mDocument, PR_TRUE); // here. Callers beware!
aKid->SetDocument(mDocument, PR_FALSE);
if (aNotify && ElementIsInDocument()) { if (aNotify && mDocument) {
mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex); mDocument->ContentReplaced(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aKid, aIndex);
} }
#if 0 //XXXwaterson put this in eventually.
// This will cause the script object to be unrooted for each // This will cause the script object to be unrooted for each
// element in the subtree. // element in the subtree.
oldKid->SetDocument(nsnull, PR_TRUE); oldKid->SetDocument(nsnull, PR_TRUE);
#endif
// We've got no mo' parent. // We've got no mo' parent.
oldKid->SetParent(nsnull); oldKid->SetParent(nsnull);
@ -2090,10 +2107,10 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this)); aKid->SetParent(NS_STATIC_CAST(nsIStyledContent*, this));
// ranges don't need adjustment since new child is at end of list // ranges don't need adjustment since new child is at end of list
//XXXwaterson this should be shallow // N.B. that this is only "shallow". Callers beware!
aKid->SetDocument(mDocument, PR_TRUE); aKid->SetDocument(mDocument, PR_FALSE);
if (aNotify && ElementIsInDocument()) { if (aNotify && mDocument) {
PRUint32 cnt; PRUint32 cnt;
rv = mChildren->Count(&cnt); rv = mChildren->Count(&cnt);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
@ -2194,15 +2211,13 @@ nsXULElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
nsIDocument* doc = mDocument; nsIDocument* doc = mDocument;
PRBool removeOk = mChildren->RemoveElementAt(aIndex); PRBool removeOk = mChildren->RemoveElementAt(aIndex);
//nsRange::OwnerChildRemoved(this, aIndex, oldKid); //nsRange::OwnerChildRemoved(this, aIndex, oldKid);
if (aNotify && removeOk && ElementIsInDocument()) { if (aNotify && removeOk && mDocument) {
doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex); doc->ContentRemoved(NS_STATIC_CAST(nsIStyledContent*, this), oldKid, aIndex);
} }
#if 0 //XXXwaterson put this in eventually
// This will cause the script object to be unrooted for each // This will cause the script object to be unrooted for each
// element in the subtree. // element in the subtree.
oldKid->SetDocument(nsnull, PR_TRUE); oldKid->SetDocument(nsnull, PR_TRUE);
#endif
// We've got no mo' parent. // We've got no mo' parent.
oldKid->SetParent(nsnull); oldKid->SetParent(nsnull);
@ -3248,37 +3263,6 @@ nsXULElement::ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsString
} }
PRBool
nsXULElement::ElementIsInDocument()
{
// Check to see if the element is really _in_ the document; that
// is, that it actually is in the tree rooted at the document's
// root content.
if (! mDocument)
return PR_FALSE;
nsresult rv;
nsCOMPtr<nsIContent> root = dont_AddRef( mDocument->GetRootContent() );
if (! root)
return PR_FALSE;
// Hack to get off scc's evil-use-of-do_QueryInterface() radar.
nsIStyledContent* p = NS_STATIC_CAST(nsIStyledContent*, this);
nsCOMPtr<nsIContent> node = do_QueryInterface(p);
while (node) {
if (node == root)
return PR_TRUE;
nsCOMPtr<nsIContent> oldNode = node;
rv = oldNode->GetParent(*getter_AddRefs(node));
if (NS_FAILED(rv)) return PR_FALSE;
}
return PR_FALSE;
}
nsresult nsresult
nsXULElement::ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent) nsXULElement::ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent)
{ {

Просмотреть файл

@ -508,8 +508,6 @@ protected:
nsresult ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsString& attrName); nsresult ExecuteOnBroadcastHandler(nsIDOMElement* anElement, const nsString& attrName);
PRBool ElementIsInDocument();
static nsresult static nsresult
ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent); ExecuteJSCode(nsIDOMElement* anElement, nsEvent* aEvent);