Eliminate nsIContent::SetDocument/SetParent/SetBindingParent in favor of

BindToTree and UnbindFromTree methods.  Bug 286000, r=sicking, sr=jst
This commit is contained in:
bzbarsky%mit.edu 2005-04-05 23:54:35 +00:00
Родитель a8306ce1ab
Коммит 9b1db9f768
55 изменённых файлов: 1372 добавлений и 822 удалений

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

@ -60,8 +60,8 @@ class nsIURI;
// IID for the nsIContent interface
#define NS_ICONTENT_IID \
{ 0x38824dfc, 0x5a2d, 0x4b86, \
{ 0x8c, 0x49, 0xcc, 0xbb, 0x70, 0x03, 0x47, 0x51 } }
{ 0x10caf6a4, 0x8891, 0x46c9, \
{ 0x9b, 0x6c, 0x6d, 0xc8, 0xdf, 0x01, 0x2d, 0x29 } }
/**
* A node of content in a document's content model. This interface
@ -82,16 +82,51 @@ public:
virtual nsIDocument* GetDocument() const = 0;
/**
* Set the document for this content.
*
* @param aDocument the new document to set (could be null)
* @param aDeep whether to set the document on children
* Bind this content node to a tree. If this method throws, the caller must
* call UnbindFromTree() on the node. In the typical case of a node being
* appended to a parent, this will be called after the node has been added to
* the parent's child list and before nsIDocumentObserver notifications for
* the addition are dispatched.
* @param aDocument The new document for the content node. Must match the
* current document of aParent, if aParent is not null.
* May not be null if aParent is null.
* @param aParent The new parent for the content node. May be null if the
* node is being bound as a direct child of the document.
* @param aBindingParent The new binding parent for the content node.
* This is allowed to be null. In that case, the
* binding parent of aParent, if any, will be used.
* @param aCompileEventHandlers whether to initialize the event handlers in
* the document (used by nsXULElement)
* @note either aDocument or aParent must be non-null. If both are null,
* this method _will_ crash.
* @note This method must not be called by consumers of nsIContent on a node
* that is already bound to a tree. Call UnbindFromTree first.
* @note This method will handle rebinding descendants appropriately (eg
* changing their binding parent as needed).
* @note This method does not add the content node to aParent's child list
* @throws NS_ERROR_OUT_OF_MEMORY if that happens
*/
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers) = 0;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers) = 0;
/**
* Unbind this content node from a tree. This will set its current document
* and binding parent to null. In the typical case of a node being removed
* from a parent, this will be called after it has been removed from the
* parent's child list and after the nsIDocumentObserver notifications for
* the removal have been dispatched.
* @param aDeep Whether to recursively unbind the entire subtree rooted at
* this node. The only time PR_FALSE should be passed is when the
* parent node of the content is being destroyed.
* @param aNullParent Whether to null out the parent pointer as well. This
* is usually desirable. This argument should only be false while
* recursively calling UnbindFromTree when a subtree is detached.
* @note This method is safe to call on nodes that are not bound to a tree.
*/
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE) = 0;
/**
* Returns true if the content has an ancestor that is a document.
*
@ -128,14 +163,6 @@ public:
return NS_REINTERPRET_CAST(nsIContent *, mParentPtrBits & ~kParentBitMask);
}
/**
* Set the parent content for this content. (This does not add the child to
* its parent's child list.) This clobbers the low 2 bits of the parent
* pointer, so subclasses which use those bits should override this.
* @param aParent the new parent content to set (could be null)
*/
virtual void SetParent(nsIContent* aParent) = 0;
/**
* Get whether this content is C++-generated anonymous content
* @see nsIAnonymousContentCreator
@ -198,6 +225,7 @@ public:
* @param aNotify whether to notify the document that the insert has
* occurred
* @param aDeepSetDocument whether to set document on all children of aKid
* XXXbz aDeepSetDocument is now unused
*/
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify, PRBool aDeepSetDocument) = 0;
@ -209,6 +237,7 @@ public:
* @param aNotify whether to notify the document that the replace has
* occurred
* @param aDeepSetDocument whether to set document on all children of aKid
* XXXbz aDeepSetDocument is now unused
*/
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify,
PRBool aDeepSetDocument) = 0;
@ -480,15 +509,6 @@ public:
return PR_FALSE;
}
/**
* Sets content node with the binding responsible for our construction (and
* existence). Used by anonymous content (XBL-generated). null for all
* explicit content.
*
* @param aContent the new binding parent
*/
virtual nsresult SetBindingParent(nsIContent* aContent) = 0;
/**
* Gets content node with the binding responsible for our construction (and
* existence). Used by anonymous content (XBL-generated). null for all

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

@ -617,7 +617,9 @@ nsAttrAndChildArray::Clear()
PRUint32 end = slotCount * ATTRSIZE + ChildCount();
for (i = slotCount * ATTRSIZE; i < end; ++i) {
nsIContent* child = NS_STATIC_CAST(nsIContent*, mImpl->mBuffer[i]);
child->SetParent(nsnull); // XXX is it better to let the owner do this?
// making this PR_FALSE so tree teardown doesn't end up being
// O(N*D) (number of nodes times average depth of tree).
child->UnbindFromTree(PR_FALSE); // XXX is it better to let the owner do this?
NS_RELEASE(child);
}

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

@ -543,13 +543,15 @@ nsDocument::~nsDocument()
}
if (mRootContent) {
if (mRootContent->GetDocument()) {
if (mRootContent->GetCurrentDoc()) {
NS_ASSERTION(mRootContent->GetCurrentDoc() == this,
"Unexpected current doc in root content");
// The root content still has a pointer back to the document,
// clear the document pointer in all children.
PRInt32 count = mChildren.Count();
for (indx = 0; indx < count; ++indx) {
mChildren[indx]->SetDocument(nsnull, PR_TRUE, PR_FALSE);
mChildren[indx]->UnbindFromTree();
}
}
}
@ -751,7 +753,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup)
for (i = 0; i < count; i++) {
nsCOMPtr<nsIContent> content = mChildren[i];
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
content->UnbindFromTree();
ContentRemoved(nsnull, content, i);
}
mChildren.Clear();
@ -1837,7 +1839,7 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
mIsGoingAway = PR_TRUE;
for (indx = 0; indx < count; ++indx) {
mChildren[indx]->SetDocument(nsnull, PR_TRUE, PR_TRUE);
mChildren[indx]->UnbindFromTree();
}
// Propagate the out-of-band notification to each PresShell's
@ -3291,7 +3293,9 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
}
indx = mChildren.Count();
mChildren.AppendObject(content);
if (!mChildren.AppendObject(content)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
else {
nsCOMPtr<nsIContent> refContent(do_QueryInterface(aRefChild));
@ -3311,7 +3315,9 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
mChildren.InsertObjectAt(content, indx);
if (!mChildren.InsertObjectAt(content, indx)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
// If we get here, we've succesfully inserted content into the
@ -3320,7 +3326,16 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
mRootContent = content;
}
content->SetDocument(this, PR_TRUE, PR_TRUE);
rv = content->BindToTree(this, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mChildren.RemoveObjectAt(indx);
if (mRootContent == content) {
mRootContent = nsnull;
}
content->UnbindFromTree();
return rv;
}
ContentInserted(nsnull, content, indx);
NS_ADDREF(*aReturn = aNewChild);
@ -3371,16 +3386,28 @@ nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
}
ContentRemoved(nsnull, refContent, indx);
refContent->SetDocument(nsnull, PR_TRUE, PR_TRUE);
mChildren.RemoveObjectAt(indx);
ContentRemoved(nsnull, refContent, indx);
refContent->UnbindFromTree();
mChildren.ReplaceObjectAt(content, indx);
// This is OK because we checked above.
if (nodeType == nsIDOMNode::ELEMENT_NODE) {
mRootContent = content;
}
content->SetDocument(this, PR_TRUE, PR_TRUE);
mChildren.InsertObjectAt(content, indx);
rv = content->BindToTree(this, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mChildren.RemoveObjectAt(indx);
if (mRootContent == content) {
mRootContent = nsnull;
}
content->UnbindFromTree();
return rv;
}
ContentInserted(nsnull, content, indx);
NS_ADDREF(*aReturn = aNewChild);
@ -3411,7 +3438,7 @@ nsDocument::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
if (content == mRootContent)
mRootContent = nsnull;
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
content->UnbindFromTree();
*aReturn = aOldChild;
NS_ADDREF(aOldChild);

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

@ -227,7 +227,11 @@ nsDocumentFragment::DisconnectChildren()
PRUint32 i, count = GetChildCount();
for (i = 0; i < count; i++) {
GetChildAt(i)->SetParent(nsnull);
NS_ASSERTION(GetChildAt(i)->GetCurrentDoc() == nsnull,
"How did we get a child with a current doc?");
// Safe to unbind PR_FALSE, since kids should never have a current document
// or a binding parent
GetChildAt(i)->UnbindFromTree(PR_FALSE);
}
return NS_OK;
@ -237,6 +241,8 @@ NS_IMETHODIMP
nsDocumentFragment::ReconnectChildren()
{
PRUint32 i, count = GetChildCount();
NS_PRECONDITION(GetCurrentDoc() == nsnull,
"We really shouldn't have a current doc!");
for (i = 0; i < count; i++) {
nsIContent *child = GetChildAt(i);
@ -246,6 +252,7 @@ nsDocumentFragment::ReconnectChildren()
// This is potentially a O(n**2) operation, but it should only
// happen in error cases (such as out of memory or something
// similar) so we don't care for now.
// XXXbz I don't think this is O(n**2) with our IndexOf cache, is it?
PRInt32 indx = parent->IndexOf(child);
@ -254,7 +261,15 @@ nsDocumentFragment::ReconnectChildren()
}
}
child->SetParent(this);
nsresult rv = child->BindToTree(nsnull, this, nsnull, PR_FALSE);
if (NS_FAILED(rv)) {
// It's all bad now... Just forget about this kid, I guess
child->UnbindFromTree();
mAttrsAndChildren.RemoveChildAt(i);
// Adjust count and iterator accordingly
--count;
--i;
}
}
return NS_OK;

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

@ -590,24 +590,64 @@ nsGenericDOMDataNode::GetDocument() const
return GetCurrentDoc();
}
void
nsGenericDOMDataNode::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
// 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
// NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
// "aDocument must be current doc of aParent");
NS_PRECONDITION(!aParent ||
(aParent->IsContentOfType(eXUL) && aDocument == nsnull) ||
aDocument == aParent->GetCurrentDoc(),
"aDocument must be current doc of aParent");
NS_PRECONDITION(!GetCurrentDoc(), "Already have a document. Unbind first!");
// Note that as we recurse into the kids, they'll have a non-null parent. So
// only assert if our parent is _changing_ while we have a parent.
NS_PRECONDITION(!GetParent() || aParent == GetParent(),
"Already have a parent. Unbind first!");
// XXXbz GetBindingParent() is broken for us, so can't assert
// anything about it yet.
// NS_PRECONDITION(!GetBindingParent() ||
// aBindingParent == GetBindingParent() ||
// (aParent &&
// aParent->GetBindingParent() == GetBindingParent()),
// "Already have a binding parent. Unbind first!");
// XXXbz we don't keep track of the binding parent yet. We should.
// Set parent
PtrBits new_bits = NS_REINTERPRET_CAST(PtrBits, aParent);
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
mParentPtrBits = new_bits;
// Set document
mDocument = aDocument;
if (mDocument && mText.IsBidi()) {
aDocument->SetBidiEnabled(PR_TRUE);
mDocument->SetBidiEnabled(PR_TRUE);
}
NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
// XXXbz GetBindingParent() is broken for us, so can't assert
// anything about it yet.
// NS_POSTCONDITION(aBindingParent = GetBindingParent(),
// "Bound to wrong binding parent");
return NS_OK;
}
void
nsGenericDOMDataNode::SetParent(nsIContent* aParent)
nsGenericDOMDataNode::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
PtrBits new_bits = NS_REINTERPRET_CAST(PtrBits, aParent);
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
mParentPtrBits = new_bits;
mDocument = nsnull;
if (aNullParent) {
mParentPtrBits &= nsIContent::kParentBitMask;
}
}
PRBool
@ -921,12 +961,6 @@ nsGenericDOMDataNode::GetBindingParent() const
return parent ? parent->GetBindingParent() : nsnull;
}
nsresult
nsGenericDOMDataNode::SetBindingParent(nsIContent* aParent)
{
return NS_OK;
}
PRBool
nsGenericDOMDataNode::IsContentOfType(PRUint32 aFlags) const
{

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

@ -166,8 +166,11 @@ public:
// Implementation for nsIContent
nsIDocument* GetDocument() const;
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
PRBool IsInDoc() const
{
return !!mDocument;
@ -190,7 +193,6 @@ public:
return parent ? parent->GetOwnerDoc() : nsnull;
}
virtual void SetParent(nsIContent* aParent);
virtual PRBool IsNativeAnonymous() const;
virtual void SetNativeAnonymous(PRBool aAnonymous);
virtual PRInt32 GetNameSpaceID() const;
@ -226,7 +228,6 @@ public:
virtual const nsVoidArray *GetRangeList() const;
virtual nsIContent *GetBindingParent() const;
virtual nsresult SetBindingParent(nsIContent* aParent);
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
virtual nsresult GetListenerManager(nsIEventListenerManager **aResult);

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

@ -1754,98 +1754,160 @@ nsGenericElement::Normalize()
return result;
}
void
nsGenericElement::SetDocumentInChildrenOf(nsIContent* aContent,
nsIDocument* aDocument,
PRBool aCompileEventHandlers)
nsresult
nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
PRUint32 i, n = aContent->GetChildCount();
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
// 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
// NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
// "aDocument must be current doc of aParent");
NS_PRECONDITION(!aParent ||
(aParent->IsContentOfType(eXUL) && aDocument == nsnull) ||
aDocument == aParent->GetCurrentDoc(),
"aDocument must be current doc of aParent");
NS_PRECONDITION(!GetCurrentDoc(), "Already have a document. Unbind first!");
// Note that as we recurse into the kids, they'll have a non-null parent. So
// only assert if our parent is _changing_ while we have a parent.
NS_PRECONDITION(!GetParent() || aParent == GetParent(),
"Already have a parent. Unbind first!");
NS_PRECONDITION(!GetBindingParent() ||
aBindingParent == GetBindingParent() ||
(!aBindingParent && aParent &&
aParent->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
if (!aBindingParent && aParent) {
aBindingParent = aParent->GetBindingParent();
}
for (i = 0; i < n; ++i) {
nsIContent *child = aContent->GetChildAt(i);
// First set the binding parent
if (aBindingParent) {
nsDOMSlots *slots = GetDOMSlots();
if (child) {
child->SetDocument(aDocument, PR_TRUE, aCompileEventHandlers);
if (!slots) {
return NS_ERROR_OUT_OF_MEMORY;
}
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
}
// Now set the parent; make sure to preserve the bits we have stashed there
// Note that checking whether aParent == GetParent() is probably not worth it
// here.
PtrBits new_bits = NS_REINTERPRET_CAST(PtrBits, aParent);
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
mParentPtrBits = new_bits;
nsresult rv;
// Finally, set the document
if (aDocument) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
// XXXbz ordering issues here? Probably not, since ChangeDocumentFor is
// just pretty broken anyway.... Need to get it working.
// XXXbz XBL doesn't handle this (asserts), and we don't really want
// to be doing this during parsing anyway... sort this out.
// aDocument->BindingManager()->ChangeDocumentFor(this, nsnull,
// aDocument);
// Being added to a document.
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
// check the document on the nodeinfo to see whether we need a
// new nodeinfo
// XXXbz sXBL/XBL2 issue!
nsIDocument *ownerDocument = GetOwnerDoc();
if (aDocument != ownerDocument) {
if (HasProperties()) {
ownerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
}
// get a new nodeinfo
nsNodeInfoManager* nodeInfoManager = aDocument->NodeInfoManager();
if (nodeInfoManager) {
nsCOMPtr<nsINodeInfo> 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);
}
}
}
// Now recurse into our kids
PRUint32 i, n = GetChildCount();
for (i = 0; i < n; ++i) {
rv = mAttrsAndChildren.ChildAt(i)->BindToTree(aDocument, this,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
}
// XXXbz script execution during binding can trigger some of these
// postcondition asserts.... But we do want that, since things will
// generally be quite broken when that happens.
NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
NS_POSTCONDITION(aBindingParent == GetBindingParent(),
"Bound to wrong binding parent");
return NS_OK;
}
void
nsGenericElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsGenericElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
"Shallow unbind won't clear document and binding parent on "
"kids!");
// Make sure to unbind this node before doing the kids
nsIDocument *document = GetCurrentDoc();
if (aDocument != document) {
// If we were part of a document, make sure we get rid of the
// script context reference to our script object so that our
// script object can be freed (or collected).
if (document) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
if (document && aDeep) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
document->BindingManager()->ChangeDocumentFor(this, document, aDocument);
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
nsCOMPtr<nsIDOMElement> domElement;
QueryInterface(NS_GET_IID(nsIDOMElement), getter_AddRefs(domElement));
if (domElement) {
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(document));
nsDoc->SetBoxObjectFor(domElement, nsnull);
}
if (domElement) {
nsCOMPtr<nsIDOMNSDocument> nsDoc = do_QueryInterface(document);
nsDoc->SetBoxObjectFor(domElement, nsnull);
}
}
if (aDocument) {
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
// check the document on the nodeinfo to see whether we need a
// new nodeinfo
// XXXbz sXBL/XBL2 issue!
nsIDocument *ownerDocument = GetOwnerDoc();
if (aDocument != ownerDocument) {
if (HasProperties()) {
ownerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
}
// get a new nodeinfo
nsNodeInfoManager* nodeInfoManager = aDocument->NodeInfoManager();
if (nodeInfoManager) {
nsCOMPtr<nsINodeInfo> newNodeInfo;
nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
mNodeInfo->GetPrefixAtom(),
mNodeInfo->NamespaceID(),
getter_AddRefs(newNodeInfo));
if (newNodeInfo) {
mNodeInfo.swap(newNodeInfo);
}
}
}
}
else {
mParentPtrBits &= ~PARENT_BIT_INDOCUMENT;
}
// Unset things in the reverse order from how we set them in BindToTree
mParentPtrBits &= ~PARENT_BIT_INDOCUMENT;
if (aNullParent) {
// Just mask it out
mParentPtrBits &= nsIContent::kParentBitMask;
}
nsDOMSlots *slots = GetExistingDOMSlots();
if (slots) {
slots->mBindingParent = nsnull;
}
if (aDeep) {
SetDocumentInChildrenOf(this, aDocument, aCompileEventHandlers);
}
}
// Do the kids
PRUint32 i, n = GetChildCount();
void
nsGenericElement::SetParent(nsIContent* aParent)
{
PtrBits new_bits = NS_REINTERPRET_CAST(PtrBits, aParent);
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
mParentPtrBits = new_bits;
if (aParent) {
nsIContent* bindingPar = aParent->GetBindingParent();
if (bindingPar)
SetBindingParent(bindingPar);
for (i = 0; i < n; ++i) {
// Note that we pass PR_FALSE for aNullParent here, since we don't want
// the kids to forget us. We _do_ want them to forget their binding
// parent, though, since this only walks non-anonymous kids.
mAttrsAndChildren.ChildAt(i)->UnbindFromTree(PR_TRUE, PR_FALSE);
}
}
}
@ -2505,30 +2567,6 @@ nsGenericElement::GetBindingParent() const
return nsnull;
}
nsresult
nsGenericElement::SetBindingParent(nsIContent* aParent)
{
nsDOMSlots *slots = GetDOMSlots();
if (!slots) {
return NS_ERROR_OUT_OF_MEMORY;
}
slots->mBindingParent = aParent; // Weak, so no addref happens.
nsresult rv = NS_OK;
if (aParent) {
PRUint32 count = GetChildCount();
for (PRUint32 i = 0; i < count; ++i) {
rv |= GetChildAt(i)->SetBindingParent(aParent);
}
}
return rv;
}
PRBool
nsGenericElement::IsContentOfType(PRUint32 aFlags) const
{
@ -2618,10 +2656,22 @@ nsGenericElement::InsertChildAt(nsIContent* aKid,
nsresult rv = mAttrsAndChildren.InsertChildAt(aKid, aIndex);
NS_ENSURE_SUCCESS(rv, rv);
aKid->SetParent(this);
rv = aKid->BindToTree(document, this, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mAttrsAndChildren.RemoveChildAt(aIndex);
aKid->UnbindFromTree();
return rv;
}
nsRange::OwnerChildInserted(this, aIndex);
if (document) {
aKid->SetDocument(document, aDeepSetDocument, PR_TRUE);
// The kid may have removed us from the document, so recheck that we're still
// in the document before proceeding. Also, the kid may have just removed
// itself, in which case we don't really want to fire ContentAppended or a
// mutation event.
// XXXbz What if the kid just moved us in the document? Scripts suck. We
// really need to stop running them while we're in the middle of modifying
// the DOM....
if (document && document == GetCurrentDoc() && aKid->GetParent() == this) {
if (aNotify) {
if (isAppend) {
document->ContentAppended(this, aIndex);
@ -2653,11 +2703,22 @@ nsGenericElement::AppendChildTo(nsIContent* aKid, PRBool aNotify,
nsresult rv = mAttrsAndChildren.AppendChild(aKid);
NS_ENSURE_SUCCESS(rv, rv);
aKid->SetParent(this);
rv = aKid->BindToTree(document, this, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mAttrsAndChildren.RemoveChildAt(GetChildCount() - 1);
aKid->UnbindFromTree();
return rv;
}
// ranges don't need adjustment since new child is at end of list
if (document) {
aKid->SetDocument(document, aDeepSetDocument, PR_TRUE);
// The kid may have removed us from the document, so recheck that we're still
// in the document before proceeding. Also, the kid may have just removed
// itself, in which case we don't really want to fire ContentAppended or a
// mutation event.
// XXXbz What if the kid just moved us in the document? Scripts suck. We
// really need to stop running them while we're in the middle of modifying
// the DOM....
if (document && document == GetCurrentDoc() && aKid->GetParent() == this) {
if (aNotify) {
document->ContentAppended(this, GetChildCount() - 1);
}
@ -2699,8 +2760,7 @@ nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
document->ContentRemoved(this, oldKid, aIndex);
}
oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE);
oldKid->SetParent(nsnull);
oldKid->UnbindFromTree();
}
return NS_OK;
@ -3267,7 +3327,9 @@ nsGenericElement::AddScriptEventListener(nsIAtom* aAttribute,
// If we have a document, and it has a script global, add the
// event listener on the global. If not, proceed as normal.
nsIDocument *document = GetCurrentDoc();
// XXXbz should we instead use GetCurrentDoc() here, override
// BindToTree for those classes and munge event listeners there?
nsIDocument *document = GetOwnerDoc();
if (document && (sgo = document->GetScriptGlobalObject())) {
nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(sgo));
NS_ENSURE_TRUE(receiver, NS_ERROR_FAILURE);

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

@ -372,8 +372,11 @@ public:
{
return IsInDoc() ? GetOwnerDoc() : nsnull;
}
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
PRBool IsInDoc() const
{
return mParentPtrBits & PARENT_BIT_INDOCUMENT;
@ -382,7 +385,6 @@ public:
{
return nsContentUtils::GetDocument(mNodeInfo);
}
virtual void SetParent(nsIContent* aParent);
virtual PRBool IsNativeAnonymous() const;
virtual void SetNativeAnonymous(PRBool aAnonymous);
virtual PRInt32 GetNameSpaceID() const;
@ -426,7 +428,6 @@ public:
virtual void SetContentID(PRUint32 aID);
virtual void SetFocus(nsPresContext* aContext);
virtual nsIContent *GetBindingParent() const;
virtual nsresult SetBindingParent(nsIContent* aParent);
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
virtual nsresult GetListenerManager(nsIEventListenerManager** aResult);
virtual already_AddRefed<nsIURI> GetBaseURI() const;

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

@ -117,13 +117,12 @@ public:
virtual ~nsAttributeTextNode() {
DetachListener();
}
virtual void SetParent(nsIContent* aParent) {
if (!aParent) {
DetachListener();
}
nsTextNode::SetParent(aParent);
}
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsRefPtr<nsAttrChangeListener> mListener; // our listener
private:
@ -305,10 +304,9 @@ nsAttributeTextNode::nsAttrChangeListener::HandleEvent(nsIDOMEvent* aEvent)
}
nsresult
NS_NewAttributeContent(nsIContent* aContent, PRInt32 aNameSpaceID,
nsIAtom* aAttrName, nsIContent** aResult)
NS_NewAttributeContent(PRInt32 aNameSpaceID, nsIAtom* aAttrName,
nsIContent** aResult)
{
NS_PRECONDITION(aContent, "Must have parent content");
NS_PRECONDITION(aAttrName, "Must have an attr name");
NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "Must know namespace");
@ -317,47 +315,73 @@ NS_NewAttributeContent(nsIContent* aContent, PRInt32 aNameSpaceID,
nsRefPtr<nsAttributeTextNode> textNode = new nsAttributeTextNode();
NS_ENSURE_TRUE(textNode, NS_ERROR_OUT_OF_MEMORY);
nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(aContent));
NS_ENSURE_TRUE(eventTarget, NS_ERROR_UNEXPECTED);
nsRefPtr<nsAttributeTextNode::nsAttrChangeListener> listener =
textNode->mListener =
new nsAttributeTextNode::nsAttrChangeListener(aNameSpaceID,
aAttrName,
textNode);
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = eventTarget->AddEventListener(NS_LITERAL_STRING("DOMAttrModified"),
listener,
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString attrValue;
aContent->GetAttr(aNameSpaceID, aAttrName, attrValue);
textNode->SetData(attrValue);
textNode->SetParent(aContent);
textNode->mListener = listener; // Now textNode going away will detach the listener automatically.
NS_ENSURE_TRUE(textNode->mListener, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult = textNode);
return NS_OK;
}
nsresult
nsAttributeTextNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
NS_PRECONDITION(aParent, "This node can't be a child of the document");
nsresult rv = nsTextNode::BindToTree(aDocument, aParent,
aBindingParent, aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (mListener) {
// Attach it to the new parent
nsCOMPtr<nsIDOMEventTarget> eventTarget(do_QueryInterface(aParent));
NS_ENSURE_TRUE(eventTarget, NS_ERROR_UNEXPECTED);
rv = eventTarget->AddEventListener(NS_LITERAL_STRING("DOMAttrModified"),
mListener,
PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString attrValue;
aParent->GetAttr(mListener->mNameSpaceID, mListener->mAttrName,
attrValue);
SetData(attrValue);
}
return NS_OK;
}
void
nsAttributeTextNode::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// Detach the listener while we know who our parent is!
if (aNullParent) {
DetachListener();
}
nsTextNode::UnbindFromTree(aDeep, aNullParent);
}
void
nsAttributeTextNode::DetachListener()
{
if (!mListener)
return;
NS_ASSERTION(GetParent(), "How did our parent go away while we still have an observer?");
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(GetParent()));
if (target) {
#ifdef DEBUG
nsresult rv =
nsresult rv =
#endif
target->RemoveEventListener(NS_LITERAL_STRING("DOMAttrModified"),
mListener,
PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(rv), "'Leaking' listener for lifetime of this page");
target->RemoveEventListener(NS_LITERAL_STRING("DOMAttrModified"),
mListener,
PR_FALSE);
NS_ASSERTION(NS_SUCCEEDED(rv), "'Leaking' listener for lifetime of this page");
}
mListener->mContent = nsnull; // Make it forget us
mListener = nsnull; // Goodbye, listener
}

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

@ -1317,22 +1317,30 @@ nsGenericHTMLElement::InNavQuirksMode(nsIDocument* aDoc)
return doc->GetCompatibilityMode() == eCompatibility_NavQuirks;
}
void
nsGenericHTMLElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsGenericHTMLElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument *document = GetCurrentDoc();
PRBool doNothing = aDocument == document; // short circuit useless work
nsGenericElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsresult rv = nsGenericElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// XXXbz if we already have a style attr parsed, this won't do
// anything... need to fix that.
ReparseStyleAttribute();
if (!doNothing && aDocument) {
if (aDocument) {
// If we're in a document now, let our mapped attrs know what their new
// sheet is.
nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
if (sheet) {
mAttrsAndChildren.SetMappedAttrStyleSheet(sheet);
}
}
return rv;
}
already_AddRefed<nsIDOMHTMLFormElement>
@ -1951,7 +1959,7 @@ nsGenericHTMLElement::GetInlineStyleRule()
if (attrVal->Type() != nsAttrValue::eCSSStyleRule) {
ReparseStyleAttribute();
attrVal = mAttrsAndChildren.GetAttr(nsHTMLAtoms::style);
// hopefully value.GetUnit() is now eHTMLUnit_CSSStyleRule
// hopefully attrVal->Type() is now nsAttrValue::eCSSStyleRule
}
if (attrVal->Type() == nsAttrValue::eCSSStyleRule) {
@ -2597,11 +2605,7 @@ nsGenericHTMLElement::ParseStyleAttribute(nsIContent* aContent,
nsresult result = NS_OK;
NS_ASSERTION(aContent->GetNodeInfo(), "If we don't have a nodeinfo, we are very screwed");
// XXX GetOwnerDoc
nsIDocument* doc = aContent->GetDocument();
if (!doc) {
doc = nsContentUtils::GetDocument(aContent->GetNodeInfo());
}
nsIDocument* doc = aContent->GetOwnerDoc();
if (doc) {
PRBool isCSS = PR_TRUE; // assume CSS until proven otherwise
@ -3240,56 +3244,53 @@ nsGenericHTMLFrameElement::IsFocusable(PRInt32 *aTabIndex)
return isFocusable;
}
void
nsGenericHTMLFormElement::SetParent(nsIContent* aParent)
nsresult
nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
// If we do any finding of the form, we need to do it after we've
// called SetParent on the superclass.
PRBool findForm = PR_FALSE;
if (!aParent && mForm) {
SetForm(nsnull);
} else if (aParent && (GetParent() || !mForm)) {
// If we have a new parent and either we had an old parent or we
// don't have a form, search for a containing form. If we didn't
// have an old parent, but we do have a form, we shouldn't do the
// search. In this case, someone (possibly the content sink) has
// already set the form for us.
findForm = PR_TRUE;
}
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsGenericHTMLElement::SetParent(aParent);
if (findForm) {
if (!mForm && aParent) {
// We now have a parent, so we may have picked up an ancestor form. Search
// for it. Note that if mForm is already set we don't want to do this,
// because that means someone (probably the content sink) has already set
// it to the right value. Also note that even if being bound here didn't
// change our parent, we still need to search, since our parent chain
// probably changed _somewhere_.
FindAndSetForm();
}
return rv;
}
void
nsGenericHTMLFormElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// Save state before doing anything if the document is being removed
if (!aDocument) {
SaveState();
}
// Save state before doing anything
SaveState();
if (aDocument && GetParent() && !mForm) {
FindAndSetForm();
} else if (!aDocument && mForm) {
// We got removed from document. We have a parent form. Check
// that the form is still in the document, and if so remove
// ourselves from the form. This keeps ghosts from appearing in
// the form's |elements| array
nsCOMPtr<nsIContent> formContent(do_QueryInterface(mForm));
if (formContent && formContent->GetDocument()) {
if (mForm) {
// Might need to unset mForm
if (aNullParent) {
// No more parent means no more form
SetForm(nsnull);
} else {
// Recheck whether we should still have an mForm.
nsCOMPtr<nsIDOMHTMLFormElement> form = FindForm();
if (!form) {
SetForm(nsnull);
}
}
}
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
nsresult
nsGenericHTMLFormElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
@ -3464,30 +3465,29 @@ nsGenericHTMLFrameElement::LoadSrc()
return rv;
}
void
nsGenericHTMLFrameElement::SetParent(nsIContent *aParent)
nsresult
nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument,
nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsGenericHTMLElement::SetParent(aParent);
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// When parent is being set to null on the element's destruction, do not
// call LoadSrc().
if (!GetParent() || !IsInDoc()) {
return;
if (aDocument) {
// We're in a document now. Kick off the frame load.
LoadSrc();
}
LoadSrc();
return rv;
}
void
nsGenericHTMLFrameElement::SetDocument(nsIDocument *aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsGenericHTMLFrameElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
const nsIDocument *old_doc = GetCurrentDoc();
nsGenericHTMLElement::SetDocument(aDocument, aDeep,
aCompileEventHandlers);
if (!aDocument && mFrameLoader) {
if (mFrameLoader) {
// This iframe is being taken out of the document, destroy the
// iframe's frame loader (doing that will tear down the window in
// this iframe).
@ -3498,12 +3498,7 @@ nsGenericHTMLFrameElement::SetDocument(nsIDocument *aDocument, PRBool aDeep,
mFrameLoader = nsnull;
}
// When document is being set to null on the element's destruction,
// or when the document is being set to what the document already
// is, do not call LoadSrc().
if (GetParent() && aDocument && aDocument != old_doc) {
LoadSrc();
}
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
nsresult

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

@ -181,8 +181,9 @@ public:
static const nsSize GetClientAreaSize(nsIFrame *aFrame);
// Implementation for nsIContent
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -829,10 +830,11 @@ public:
}
// nsIContent
virtual void SetParent(nsIContent *aParent);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -887,9 +889,11 @@ public:
// nsIContent
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);
virtual void SetParent(nsIContent *aParent);
virtual void SetDocument(nsIDocument *aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{

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

@ -98,8 +98,11 @@ public:
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefURI(nsIURI** aURI);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual void SetFocus(nsPresContext* aPresContext);
virtual PRBool IsFocusable(PRBool *aTabIndex = nsnull);
@ -168,24 +171,31 @@ NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, Type, type)
NS_IMPL_STRING_ATTR(nsHTMLAnchorElement, AccessKey, accesskey)
void
nsHTMLAnchorElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument *document = GetCurrentDoc();
PRBool documentChanging = (aDocument != document);
// Unregister the access key for the old document.
if (documentChanging && document) {
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
return rv;
}
void
nsHTMLAnchorElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
if (IsInDoc()) {
RegUnRegAccessKey(PR_FALSE);
}
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
// Register the access key for the new document.
if (documentChanging && aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
NS_IMETHODIMP
@ -245,7 +255,6 @@ nsHTMLAnchorElement::IsFocusable(PRInt32 *aTabIndex)
return PR_FALSE;
}
PRBool isFocusable = PR_FALSE;
if (!HasAttr(kNameSpaceID_None, nsHTMLAtoms::tabindex)) {
// check whether we're actually a link
nsCOMPtr<nsIURI> linkURI = nsContentUtils::GetLinkURI(this);

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

@ -88,8 +88,11 @@ public:
nsEventStatus* aEventStatus);
virtual void SetFocus(nsPresContext* aPresContext);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -201,24 +204,31 @@ nsHTMLAreaElement::SetFocus(nsPresContext* aPresContext)
}
}
void
nsHTMLAreaElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument *document = GetCurrentDoc();
PRBool documentChanging = (aDocument != document);
// Unregister the access key for the old document.
if (documentChanging && document) {
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
return rv;
}
void
nsHTMLAreaElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
if (IsInDoc()) {
RegUnRegAccessKey(PR_FALSE);
}
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
// Register the access key for the new document.
if (documentChanging && aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
nsresult

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

@ -109,8 +109,8 @@ public:
virtual PRBool ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
@ -413,17 +413,16 @@ nsHTMLBodyElement::ParseAttribute(nsIAtom* aAttribute,
}
void
nsHTMLBodyElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsHTMLBodyElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsIDocument *document = GetCurrentDoc();
if (aDocument != document && mContentStyleRule) {
if (mContentStyleRule) {
mContentStyleRule->mPart = nsnull;
// destroy old style rule since the sheet will probably change
// destroy old style rule
NS_RELEASE(mContentStyleRule);
}
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
static

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

@ -171,8 +171,11 @@ public:
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -614,25 +617,36 @@ nsHTMLFormElement::ParseAttribute(nsIAtom* aAttribute,
return nsGenericHTMLElement::ParseAttribute(aAttribute, aValue, aResult);
}
void
nsHTMLFormElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsCOMPtr<nsIHTMLDocument> oldDocument = do_QueryInterface(GetCurrentDoc());
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsCOMPtr<nsIHTMLDocument> newDocument = do_QueryInterface(GetCurrentDoc());
if (oldDocument != newDocument) {
if (oldDocument) {
oldDocument->RemovedForm();
ForgetCurrentSubmission();
}
if (newDocument) {
newDocument->AddedForm();
}
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(aDocument));
if (htmlDoc) {
htmlDoc->AddedForm();
}
return rv;
}
void
nsHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIHTMLDocument> oldDocument = do_QueryInterface(GetCurrentDoc());
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
if (oldDocument) {
oldDocument->RemovedForm();
}
ForgetCurrentSubmission();
}
nsresult
nsHTMLFormElement::HandleDOMEvent(nsPresContext* aPresContext,

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

@ -141,9 +141,9 @@ public:
// XXXbz What about UnsetAttr? We don't seem to unload images when
// that happens...
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual void SetParent(nsIContent* aParent);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
protected:
void GetImageFrame(nsIImageFrame** aImageFrame);
@ -581,37 +581,25 @@ nsHTMLImageElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
aNotify);
}
void
nsHTMLImageElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
PRBool documentChanging = aDocument && aDocument != GetCurrentDoc();
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
if (documentChanging && GetParent()) {
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
nsAutoString uri;
nsresult result = GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, uri);
if (result == NS_CONTENT_ATTR_HAS_VALUE) {
ImageURIChanged(uri);
}
}
}
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
void
nsHTMLImageElement::SetParent(nsIContent* aParent)
{
nsGenericHTMLElement::SetParent(aParent);
if (aParent && IsInDoc()) {
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
nsAutoString uri;
nsresult result = GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, uri);
if (result == NS_CONTENT_ATTR_HAS_VALUE) {
ImageURIChanged(uri);
}
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
nsAutoString uri;
nsresult result = GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, uri);
if (result == NS_CONTENT_ATTR_HAS_VALUE) {
ImageURIChanged(uri);
}
return rv;
}
NS_IMETHODIMP

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

@ -187,10 +187,12 @@ public:
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
nsEventStatus* aEventStatus);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual void SetParent(nsIContent* aParent);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -896,9 +898,7 @@ nsHTMLInputElement::GetRadioGroupContainer()
nsIRadioGroupContainer* retval = nsnull;
if (mForm) {
CallQueryInterface(mForm, &retval);
} else if (GetParent()) {
// XXXbz the GetParent() check is needed because we sometimes have a doc
// when we're not really in one, I think... Need BindToTree!
} else {
nsIDocument* currentDoc = GetCurrentDoc();
if (currentDoc) {
CallQueryInterface(currentDoc, &retval);
@ -1674,24 +1674,17 @@ nsHTMLInputElement::HandleDOMEvent(nsPresContext* aPresContext,
}
void
nsHTMLInputElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
PRBool documentChanging = (aDocument != GetCurrentDoc());
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// SetDocument() sets the form and that takes care of form's WillRemove
// so we just have to take care of the case where we're removing from the
// document and we don't have a form
if (documentChanging && !mForm && mType == NS_FORM_INPUT_RADIO) {
WillRemoveFromRadioGroup();
}
nsGenericHTMLFormElement::SetDocument(aDocument, aDeep,
aCompileEventHandlers);
if (mType == NS_FORM_INPUT_IMAGE &&
documentChanging && aDocument && GetParent()) {
if (mType == NS_FORM_INPUT_IMAGE) {
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
nsAutoString uri;
@ -1700,12 +1693,15 @@ nsHTMLInputElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
ImageURIChanged(uri);
}
}
// If this is radio button which is in a form,
// and the parser is still creating the element.
// XXXbz hmmm Do we need this BF_PARSER_CREATING thing? I suspect
// we don't and that it was a hackaround around the way-early
// SetDocument call in the parser.
if (mForm || mType != NS_FORM_INPUT_RADIO ||
GET_BOOLBIT(mBitField, BF_PARSER_CREATING)) {
return;
return rv;
}
// Add radio to document if we don't have a form already (if we do it's
@ -1713,21 +1709,23 @@ nsHTMLInputElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
if (aDocument && !mForm && mType == NS_FORM_INPUT_RADIO) {
AddedToRadioGroup();
}
return rv;
}
void
nsHTMLInputElement::SetParent(nsIContent* aParent)
nsHTMLInputElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsGenericHTMLFormElement::SetParent(aParent);
if (mType == NS_FORM_INPUT_IMAGE && aParent && IsInDoc()) {
// Our base URI may have changed; claim that our URI changed, and the
// nsImageLoadingContent will decide whether a new image load is warranted.
nsAutoString uri;
nsresult result = GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, uri);
if (result == NS_CONTENT_ATTR_HAS_VALUE) {
ImageURIChanged(uri);
}
// If we have a form and are unbound from it,
// nsGenericHTMLFormElement::SetDocument() will unset the form and
// that takes care of form's WillRemove so we just have to take care
// of the case where we're removing from the document and we don't
// have a form
if (!mForm && mType == NS_FORM_INPUT_RADIO) {
WillRemoveFromRadioGroup();
}
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
}
static const nsAttrValue::EnumTable kInputTypeTable[] = {

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

@ -82,8 +82,11 @@ public:
nsIContent* aSubmitElement);
// nsIContent
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
PRUint32 aFlags,
@ -155,25 +158,31 @@ nsHTMLLabelElement::GetForm(nsIDOMHTMLFormElement** aForm)
NS_IMPL_STRING_ATTR(nsHTMLLabelElement, AccessKey, accesskey)
NS_IMPL_STRING_ATTR(nsHTMLLabelElement, HtmlFor, _for)
void
nsHTMLLabelElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLLabelElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument *document = GetCurrentDoc();
PRBool documentChanging = (aDocument != document);
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
// Unregister the access key for the old document.
if (documentChanging && document) {
if (aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
return rv;
}
void
nsHTMLLabelElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
if (IsInDoc()) {
RegUnRegAccessKey(PR_FALSE);
}
nsGenericHTMLFormElement::SetDocument(aDocument, aDeep,
aCompileEventHandlers);
// Register the access key for the new document.
if (documentChanging && aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
}
static PRBool

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

@ -79,8 +79,11 @@ public:
nsIContent* aSubmitElement);
// nsIContent
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual void SetFocus(nsPresContext* aPresContext);
virtual PRBool ParseAttribute(nsIAtom* aAttribute,
const nsAString& aValue,
@ -214,25 +217,31 @@ nsHTMLLegendElement::Reset()
return NS_OK;
}
void
nsHTMLLegendElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLLegendElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument *document = GetCurrentDoc();
PRBool documentChanging = (aDocument != document);
// Unregister the access key for the old document.
if (documentChanging && document) {
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) {
RegUnRegAccessKey(PR_TRUE);
}
return rv;
}
void
nsHTMLLegendElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
if (IsInDoc()) {
RegUnRegAccessKey(PR_FALSE);
}
nsGenericHTMLFormElement::SetDocument(aDocument, aDeep,
aCompileEventHandlers);
// Register the access key for the new document.
if (documentChanging && document) {
RegUnRegAccessKey(PR_TRUE);
}
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
}
void

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

@ -86,11 +86,12 @@ public:
NS_IMETHOD SetLinkState(nsLinkState aState);
NS_IMETHOD GetHrefURI(nsIURI** aURI);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsString& aRel,
const nsString& aRev,
const nsAString& aEventName);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -189,36 +190,52 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Rev, rev)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Target, target)
NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type)
nsresult
nsHTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
UpdateStyleSheet(nsnull);
// XXXbz we really shouldn't fire the event until after we've finished with
// the outermost BindToTree... In particular, this can effectively cause us
// to reenter this code, or for some part of the document to become unbound
// inside the event!
CreateAndDispatchEvent(aDocument, NS_LITERAL_STRING("DOMLinkAdded"));
return rv;
}
void
nsHTMLLinkElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsHTMLLinkElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
// XXXbz we really shouldn't fire the event until after we've finished with
// the outermost UnbindFromTree... In particular, this can effectively cause
// us to reenter this code, or to be bound to a different tree inside the
// event!
CreateAndDispatchEvent(oldDoc, NS_LITERAL_STRING("DOMLinkRemoved"));
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheet(oldDoc);
}
void
nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
const nsAString& aEventName)
{
if (!aDoc)
return;
nsAutoString rel;
nsAutoString rev;
GetAttr(kNameSpaceID_None, nsHTMLAtoms::rel, rel);
GetAttr(kNameSpaceID_None, nsHTMLAtoms::rev, rev);
CreateAndDispatchEvent(oldDoc, rel, rev,
NS_LITERAL_STRING("DOMLinkRemoved"));
// Do the removal and addition into the new doc.
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
UpdateStyleSheet(oldDoc);
CreateAndDispatchEvent(aDocument, rel, rev,
NS_LITERAL_STRING("DOMLinkAdded"));
}
void
nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
const nsString& aRel,
const nsString& aRev,
const nsAString& aEventName)
{
if (!aDoc)
return;
// In the unlikely case that both rev is specified *and* rel=stylesheet,
// this code will cause the event to fire, on the principle that maybe the
@ -226,8 +243,8 @@ nsHTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
// this should never actually happen and the performance hit is minimal,
// doing the "right" thing costs virtually nothing here, even if it doesn't
// make much sense.
if (aRev.IsEmpty() &&
(aRel.IsEmpty() || aRel.LowerCaseEqualsLiteral("stylesheet")))
if (rev.IsEmpty() &&
(rel.IsEmpty() || rel.LowerCaseEqualsLiteral("stylesheet")))
return;
nsCOMPtr<nsIDOMDocumentEvent> docEvent(do_QueryInterface(aDoc));

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

@ -68,9 +68,11 @@ public:
// nsIDOMHTMLMapElement
NS_DECL_NSIDOMHTMLMAPELEMENT
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
protected:
nsRefPtr<nsContentList> mAreas;
};
@ -103,33 +105,36 @@ NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLMapElement, nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_MAP_END
void
nsHTMLMapElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLMapElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument *document = GetCurrentDoc();
PRBool documentChanging = (aDocument != document);
if (documentChanging) {
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(document);
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (htmlDoc) {
htmlDoc->RemoveImageMap(this);
}
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
if (htmlDoc) {
htmlDoc->AddImageMap(this);
}
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
if (documentChanging) {
// Since we changed the document, gotta re-QI
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
if (htmlDoc) {
htmlDoc->AddImageMap(this);
}
}
return rv;
}
void
nsHTMLMapElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(GetCurrentDoc());
if (htmlDoc) {
htmlDoc->RemoveImageMap(this);
}
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
NS_IMPL_DOM_CLONENODE(nsHTMLMapElement)

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

@ -346,8 +346,10 @@ public:
virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,
PRBool aNotify);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify, PRBool aDeepSetDocument);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify,
@ -437,14 +439,21 @@ nsHTMLScriptElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
return rv;
}
void
nsHTMLScriptElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) {
MaybeProcessScript();
}
return rv;
}
nsresult
@ -639,7 +648,7 @@ nsHTMLScriptElement::GetScriptLineNumber()
void
nsHTMLScriptElement::MaybeProcessScript()
{
if (mIsEvaluated || mEvaluating || !IsInDoc() || !GetParent()) {
if (mIsEvaluated || mEvaluating || !IsInDoc()) {
return;
}

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

@ -79,8 +79,11 @@ public:
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify,
PRBool aDeepSetDocument);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -210,17 +213,30 @@ nsHTMLStyleElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
return rv;
}
nsresult
nsHTMLStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
UpdateStyleSheet(nsnull);
return rv;
}
void
nsHTMLStyleElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsHTMLStyleElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
nsGenericHTMLElement::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheet(oldDoc);
}
nsresult
nsHTMLStyleElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,

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

@ -703,6 +703,8 @@ public:
// appended to it's parent until the container is closed. By setting
// pre-append to true, the container will be appended when it is
// created.
// XXXbz why do we really need this "no pre-appending" thing? Seems
// a little weird to me....
void SetPreAppend(PRBool aPreAppend)
{
mPreAppend = aPreAppend;
@ -1237,7 +1239,6 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
mStack[mStackPos].mFlags = 0;
mStack[mStackPos].mNumFlushed = 0;
mStack[mStackPos].mInsertionPoint = -1;
content->SetDocument(mSink->mDocument, PR_FALSE, PR_TRUE);
// Make sure to add base tag info, if needed, before setting any other
// attributes -- what URI attrs do will depend on the base URI. Only do this
@ -1477,9 +1478,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
mSink->mCurrentForm, mSink->mDocShell);
NS_ENSURE_TRUE(content, NS_ERROR_OUT_OF_MEMORY);
// Set the content's document
content->SetDocument(mSink->mDocument, PR_FALSE, PR_TRUE);
// Make sure to add base tag info, if needed, before setting any other
// attributes -- what URI attrs do will depend on the base URI. Only do
// this for elements that have useful URI attributes.
@ -1607,8 +1605,6 @@ SinkContext::AddComment(const nsIParserNode& aNode)
domComment->AppendData(aNode.GetText());
comment->SetDocument(mSink->mDocument, PR_FALSE, PR_TRUE);
NS_ASSERTION(mStackPos > 0, "stack out of bounds");
if (mStackPos <= 0) {
return NS_ERROR_FAILURE;
@ -1875,9 +1871,6 @@ SinkContext::FlushText(PRBool* aDidFlush, PRBool aReleaseLast)
mLastTextNode = textContent;
// Set the content's document
mLastTextNode->SetDocument(mSink->mDocument, PR_FALSE, PR_TRUE);
// Set the text in the text node
mLastTextNode->SetText(mText, mTextLength, PR_FALSE);
@ -2176,7 +2169,11 @@ HTMLContentSink::Init(nsIDocument* aDoc,
}
NS_ADDREF(mRoot);
mRoot->SetDocument(mDocument, PR_FALSE, PR_TRUE);
rv = mRoot->BindToTree(mDocument, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mRoot->UnbindFromTree();
return rv;
}
mDocument->SetRootContent(mRoot);
}
@ -3188,7 +3185,6 @@ HTMLContentSink::SetDocumentTitle(const nsAString& aTitle, const nsIParserNode*
text->SetText(title, PR_TRUE);
it->AppendChildTo(text, PR_FALSE, PR_FALSE);
text->SetDocument(mDocument, PR_FALSE, PR_TRUE);
mHead->AppendChildTo(it, PR_FALSE, PR_FALSE);
@ -3710,9 +3706,6 @@ HTMLContentSink::ProcessAREATag(const nsIParserNode& aNode)
return NS_ERROR_OUT_OF_MEMORY;
}
// Set the content's document
area->SetDocument(mDocument, PR_FALSE, PR_TRUE);
// Make sure to add base tag info, if needed, before setting any other
// attributes -- what URI attrs do will depend on the base URI. Only do this
// for elements that have useful URI attributes.
@ -3844,9 +3837,8 @@ HTMLContentSink::ProcessBASETag(const nsIParserNode& aNode)
element->SetContentID(mDocument->GetAndIncrementContentID());
// Add in the attributes and add the style content object to the
// Add in the attributes and add the base content object to the
// head container.
element->SetDocument(mDocument, PR_FALSE, PR_TRUE);
result = AddAttributes(aNode, element);
NS_ENSURE_SUCCESS(result, result);
@ -3904,7 +3896,6 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
// Add in the attributes and add the style content object to the
// head container.
element->SetDocument(mDocument, PR_FALSE, PR_TRUE);
AddBaseTagInfo(element);
result = AddAttributes(aNode, element);
if (NS_FAILED(result)) {
@ -3991,7 +3982,6 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
// Add in the attributes and add the meta content object to the head
// container.
it->SetDocument(mDocument, PR_FALSE, PR_TRUE);
AddBaseTagInfo(it);
rv = AddAttributes(aNode, it);
if (NS_FAILED(rv)) {
@ -4180,9 +4170,8 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
element->SetContentID(mDocument->GetAndIncrementContentID());
// Add in the attributes and add the style content object to the
// Add in the attributes and add the script content object to the
// head container.
element->SetDocument(mDocument, PR_FALSE, PR_TRUE);
AddBaseTagInfo(element);
rv = AddAttributes(aNode, element);
if (NS_FAILED(rv)) {
@ -4214,7 +4203,6 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
text->SetText(script, PR_TRUE);
element->AppendChildTo(text, PR_FALSE, PR_FALSE);
text->SetDocument(mDocument, PR_FALSE, PR_TRUE);
}
nsCOMPtr<nsIScriptLoader> loader;
@ -4241,6 +4229,13 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
mScriptElements.AppendObject(sele);
}
// Now flush out tags so that the script will actually be bound to a
// document and will evaluate as soon as it's appended.
SINK_TRACE(SINK_TRACE_CALLS,
("HTMLContentSink::ProcessSCRIPTTag: flushing tags before "
"appending script"));
mCurrentContext->FlushTags(PR_FALSE);
// Insert the child into the content tree. This will evaluate the
// script as well.
if (mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mInsertionPoint != -1) {
@ -4312,7 +4307,6 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode)
// Add in the attributes and add the style content object to the
// head container.
element->SetDocument(mDocument, PR_FALSE, PR_TRUE);
AddBaseTagInfo(element);
rv = AddAttributes(aNode, element);
if (NS_FAILED(rv)) {

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

@ -93,7 +93,7 @@ public:
virtual already_AddRefed<nsContentList> GetFormControlElements() = 0;
/**
* Called when form->SetDocument() is called so that document knows
* Called when form->BindToTree() is called so that document knows
* immediately when a form is added
*/
virtual void AddedForm() = 0;

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

@ -587,7 +587,6 @@ nsImageDocument::CreateSyntheticDocument()
if (!mImageContent) {
return NS_ERROR_OUT_OF_MEMORY;
}
mImageContent->SetDocument(this, PR_FALSE, PR_TRUE);
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mImageContent);
NS_ENSURE_TRUE(imageLoader, NS_ERROR_UNEXPECTED);

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

@ -242,7 +242,11 @@ nsMediaDocument::CreateSyntheticDocument()
if (!root) {
return NS_ERROR_OUT_OF_MEMORY;
}
root->SetDocument(this, PR_FALSE, PR_TRUE);
rv = root->BindToTree(this, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
root->UnbindFromTree();
return rv;
}
SetRootContent(root);
rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::body, nsnull,
@ -254,7 +258,6 @@ nsMediaDocument::CreateSyntheticDocument()
if (!body) {
return NS_ERROR_OUT_OF_MEMORY;
}
body->SetDocument(this, PR_FALSE, PR_TRUE);
mBodyContent = do_QueryInterface(body);
root->AppendChildTo(body, PR_FALSE, PR_FALSE);

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

@ -180,7 +180,6 @@ nsPluginDocument::CreateSyntheticPluginDocument()
if (!mPluginContent) {
return NS_ERROR_OUT_OF_MEMORY;
}
mPluginContent->SetDocument(this, PR_FALSE, PR_TRUE);
// make it a named element
mPluginContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::name,

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

@ -102,12 +102,26 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericElement)
//----------------------------------------------------------------------
// nsIContent methods
void
nsSVGElement::SetParent(nsIContent* aParent)
nsresult
nsSVGElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsGenericElement::SetParent(aParent);
nsresult rv = nsGenericElement::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
ParentChainChanged();
return rv;
}
void
nsSVGElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsGenericElement::UnbindFromTree(aDeep, aNullParent);
ParentChainChanged();
}
nsIAtom *
@ -241,17 +255,6 @@ nsSVGElement::UnsetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
return nsGenericElement::UnsetAttr(aNamespaceID, aName, aNotify);
}
nsresult
nsSVGElement::SetBindingParent(nsIContent* aParent)
{
nsresult rv = nsGenericElement::SetBindingParent(aParent);
// XXX Are parent and bindingparent always in sync? (in which case
// we don't have to call ParentChainChanged() here)
ParentChainChanged();
return rv;
}
PRBool
nsSVGElement::IsContentOfType(PRUint32 aFlags) const
{

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

@ -69,7 +69,11 @@ public:
// nsIContent interface methods
virtual void SetParent(nsIContent* aParent);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsIAtom *GetIDAttributeName() const;
virtual nsIAtom *GetClassAttributeName() const;
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
@ -83,7 +87,6 @@ public:
virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
PRBool aNotify);
virtual nsresult SetBindingParent(nsIContent* aParent);
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker);

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

@ -95,8 +95,9 @@ public:
nsISVGValue::modificationType aModType);
// nsIContent specializations:
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify, PRBool aDeepSetDocument);
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify,
@ -356,14 +357,21 @@ nsSVGScriptElement::DidModifySVGObservable(nsISVGValue* aObservable,
//----------------------------------------------------------------------
// nsIContent methods
void
nsSVGScriptElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsSVGScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsSVGScriptElementBase::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsresult rv = nsSVGScriptElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (aDocument) {
MaybeProcessScript();
}
return rv;
}
nsresult
@ -400,7 +408,7 @@ nsSVGScriptElement::AppendChildTo(nsIContent* aKid, PRBool aNotify,
void
nsSVGScriptElement::MaybeProcessScript()
{
if (mIsEvaluated || mEvaluating || !IsInDoc() || !GetParent()) {
if (mIsEvaluated || mEvaluating || !IsInDoc()) {
return;
}

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

@ -70,8 +70,11 @@ public:
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify,
PRBool aDeepSetDocument);
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
const nsAString& aValue, PRBool aNotify)
{
@ -181,17 +184,30 @@ nsSVGStyleElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
return rv;
}
nsresult
nsSVGStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsresult rv = nsSVGStyleElementBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
UpdateStyleSheet(nsnull);
return rv;
}
void
nsSVGStyleElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsSVGStyleElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
nsSVGStyleElementBase::SetDocument(aDocument, aDeep, aCompileEventHandlers);
nsSVGStyleElementBase::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheet(oldDoc);
}
nsresult
nsSVGStyleElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsIAtom* aPrefix, const nsAString& aValue,

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

@ -407,7 +407,11 @@ NS_IMETHODIMP
nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocument,
nsIDocument* aNewDocument)
{
// XXXbz this code is pretty broken, since moving from one document
// to another always passes through a null document!
NS_PRECONDITION(aOldDocument != nsnull, "no old document");
NS_PRECONDITION(!aNewDocument,
"Changing to a non-null new document not supported yet");
if (! aOldDocument)
return NS_ERROR_NULL_POINTER;
@ -432,6 +436,8 @@ nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocum
// See if the element has nsIAnonymousContentCreator-created
// anonymous content...
// XXXbz this really doesn't belong here, somehow... either that, or we
// need to better define what sort of bindings we're managing.
nsCOMPtr<nsISupportsArray> anonymousElements;
shell->GetAnonymousContentFor(aContent, getter_AddRefs(anonymousElements));
@ -447,9 +453,12 @@ nsBindingManager::ChangeDocumentFor(nsIContent* aContent, nsIDocument* aOldDocum
if (! content)
continue;
content->SetDocument(aNewDocument, PR_TRUE, PR_TRUE);
content->UnbindFromTree();
}
}
// now clear out the anonymous content for this node in the old presshell.
shell->SetAnonymousContentFor(aContent, nsnull);
}
return NS_OK;

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

@ -191,19 +191,27 @@ nsXBLBinding::InstallAnonymousContent(nsIContent* aAnonParent, nsIContent* aElem
// We need to ensure two things.
// (1) The anonymous content should be fooled into thinking it's in the bound
// element's document, assuming that the bound element is in a document
nsIDocument* doc = aElement->GetCurrentDoc();
if (doc) {
aAnonParent->SetDocument(doc, PR_TRUE, AllowScripts());
}
// Note that we don't change the current doc of aAnonParent here, since that
// quite simply does not matter. aAnonParent is just a way of keeping refs
// to all its kids, which are anonymous content from the point of view of
// aElement.
// (2) The children's parent back pointer should not be to this synthetic root
// but should instead point to the enclosing parent element.
nsIDocument* doc = aElement->GetCurrentDoc();
PRBool allowScripts = AllowScripts();
PRUint32 childCount = aAnonParent->GetChildCount();
for (PRUint32 i = 0; i < childCount; i++) {
nsIContent *child = aAnonParent->GetChildAt(i);
child->SetParent(aElement);
child->SetBindingParent(mBoundElement);
child->UnbindFromTree();
nsresult rv =
child->BindToTree(doc, aElement, mBoundElement, allowScripts);
if (NS_FAILED(rv)) {
// Oh, well... Just give up.
// XXXbz This really shouldn't be a void method!
child->UnbindFromTree();
return;
}
#ifdef MOZ_XUL
// To make XUL templates work (and other goodies that happen when
@ -410,7 +418,7 @@ ChangeDocumentForDefaultContent(nsHashKey* aKey, void* aData, void* aClosure)
nsCOMPtr<nsIContent> defContent = currPoint->GetDefaultContent();
if (defContent)
defContent->SetDocument(nsnull, PR_TRUE, PR_TRUE);
defContent->UnbindFromTree();
}
return PR_TRUE;
@ -909,7 +917,7 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen
nsCOMPtr<nsIXULDocument> xuldoc(do_QueryInterface(aOldDocument));
#endif
anonymous->SetDocument(nsnull, PR_TRUE, PR_TRUE); // Kill it.
anonymous->UnbindFromTree(); // Kill it.
#ifdef MOZ_XUL
// To make XUL templates work (and other XUL-specific stuff),

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

@ -141,6 +141,15 @@ private:
class nsXBLInsertionPointEntry {
public:
~nsXBLInsertionPointEntry() {
if (mDefaultContent) {
// mDefaultContent is a sort of anonymous content within the XBL
// document, and we own and manage it. Unhook it here, since we're going
// away.
mDefaultContent->UnbindFromTree();
}
}
nsIContent* GetInsertionParent() { return mInsertionParent; }
PRUint32 GetInsertionIndex() { return mInsertionIndex; }
void SetInsertionIndex(PRUint32 aIndex) { mInsertionIndex = aIndex; }
@ -1186,7 +1195,14 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent)
// to work with on default content.
// XXXbz this is somewhat screwed up, since it's sort of like anonymous
// content... but not.
child->SetParent(parent);
nsresult rv =
child->BindToTree(parent->GetCurrentDoc(), parent, nsnull, PR_FALSE);
if (NS_FAILED(rv)) {
// Well... now what? Just unbind and bail out, I guess...
// XXXbz This really shouldn't be a void method!
child->UnbindFromTree();
return;
}
}
}
}

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

@ -62,9 +62,12 @@ public:
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
// nsIContent
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
// nsStyleLinkElement
NS_IMETHOD GetCharset(nsAString& aCharset);
@ -102,17 +105,29 @@ nsXMLStylesheetPI::~nsXMLStylesheetPI()
// nsIContent
void
nsXMLStylesheetPI::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsXMLStylesheetPI::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
nsXMLProcessingInstruction::SetDocument(aDocument, aDeep,
aCompileEventHandlers);
nsresult rv = nsXMLProcessingInstruction::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
UpdateStyleSheet(oldDoc);
UpdateStyleSheet(nsnull);
return rv;
}
void
nsXMLStylesheetPI::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIDocument> oldDoc = GetCurrentDoc();
nsXMLProcessingInstruction::UnbindFromTree(aDeep, aNullParent);
UpdateStyleSheet(oldDoc);
}
// nsIDOMNode

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

@ -743,9 +743,6 @@ nsXMLContentSink::FlushText(PRBool aCreateTextNode, PRBool* aDidFlush)
rv = NS_NewTextNode(getter_AddRefs(textContent));
NS_ENSURE_SUCCESS(rv, rv);
// Set the content's document
textContent->SetDocument(mDocument, PR_FALSE, PR_TRUE);
// Set the text in the text node
textContent->SetText(mText, mTextLength, PR_FALSE);
@ -877,6 +874,13 @@ nsXMLContentSink::SetDocElement(PRInt32 aNameSpaceID,
mDocElement = aContent;
NS_ADDREF(mDocElement);
nsresult rv = mDocElement->BindToTree(mDocument, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mDocElement->UnbindFromTree();
// If we return PR_FALSE here, the caller will bail out because it won't
// find a parent content node to append to, which is fine.
return PR_FALSE;
}
mDocument->SetRootContent(mDocElement);
return PR_TRUE;
}
@ -927,7 +931,6 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
if (mDocument) {
content->SetContentID(mDocument->GetAndIncrementContentID());
}
content->SetDocument(mDocument, PR_FALSE, PR_TRUE);
// Set the ID attribute atom on the node info object for this node
// This must occur before the attributes are added so the name
@ -1040,7 +1043,6 @@ nsXMLContentSink::HandleComment(const PRUnichar *aName)
nsCOMPtr<nsIDOMComment> domComment = do_QueryInterface(comment, &result);
if (domComment) {
domComment->AppendData(nsDependentString(aName));
comment->SetDocument(mDocument, PR_FALSE, PR_TRUE);
result = AddContentAsLeaf(comment);
}
}
@ -1064,7 +1066,6 @@ nsXMLContentSink::HandleCDataSection(const PRUnichar *aData,
nsCOMPtr<nsIDOMCDATASection> domCDATA = do_QueryInterface(cdata);
if (domCDATA) {
domCDATA->SetData(nsDependentString(aData, aLength));
cdata->SetDocument(mDocument, PR_FALSE, PR_TRUE);
result = AddContentAsLeaf(cdata);
}
}

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

@ -115,46 +115,83 @@ nsXTFElementWrapper::QueryInterface(REFNSIID aIID, void** aInstancePtr)
//----------------------------------------------------------------------
// nsIContent methods:
void
nsXTFElementWrapper::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsXTFElementWrapper::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
// XXX For some reason we often get 2 SetDocument notifications with
// identical aDocument (one when expat encounters the element and
// another when the element is appended to its parent). We want to
// make sure that we only route notifications if the document has
// actually changed.
bool docReallyChanged = false;
if (aDocument!=GetCurrentDoc()) docReallyChanged = true;
// XXXbz making up random order for the notifications... Perhaps
// this api should more closely match BindToTree/UnbindFromTree?
nsCOMPtr<nsIDOMElement> domParent;
if (aParent != GetParent()) {
domParent = do_QueryInterface(aParent);
}
nsCOMPtr<nsIDOMDocument> domDocument;
if (docReallyChanged &&
mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT |
nsIXTFElement::NOTIFY_DOCUMENT_CHANGED))
if (aDocument &&
(mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT |
nsIXTFElement::NOTIFY_DOCUMENT_CHANGED))) {
domDocument = do_QueryInterface(aDocument);
if (docReallyChanged &&
(mNotificationMask & nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT))
}
if (domDocument &&
(mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT))) {
GetXTFElement()->WillChangeDocument(domDocument);
nsXTFElementWrapperBase::SetDocument(aDocument, aDeep, aCompileEventHandlers);
if (docReallyChanged &&
(mNotificationMask & nsIXTFElement::NOTIFY_DOCUMENT_CHANGED))
}
if (domParent &&
(mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT))) {
GetXTFElement()->WillChangeParent(domParent);
}
nsresult rv = nsXTFElementWrapperBase::BindToTree(aDocument, aParent,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
if (domDocument &&
(mNotificationMask & (nsIXTFElement::NOTIFY_DOCUMENT_CHANGED))) {
GetXTFElement()->DocumentChanged(domDocument);
}
if (domParent &&
(mNotificationMask & (nsIXTFElement::NOTIFY_PARENT_CHANGED))) {
GetXTFElement()->ParentChanged(domParent);
}
return rv;
}
void
nsXTFElementWrapper::SetParent(nsIContent* aParent)
nsXTFElementWrapper::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
nsCOMPtr<nsIDOMElement> domParent;
if (mNotificationMask & (nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT |
nsIXTFElement::NOTIFY_PARENT_CHANGED))
domParent = do_QueryInterface(aParent);
if (mNotificationMask & nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT)
GetXTFElement()->WillChangeParent(domParent);
nsXTFElementWrapperBase::SetParent(aParent);
if (mNotificationMask & nsIXTFElement::NOTIFY_PARENT_CHANGED)
GetXTFElement()->ParentChanged(domParent);
// XXXbz making up random order for the notifications... Perhaps
// this api should more closely match BindToTree/UnbindFromTree?
PRBool inDoc = IsInDoc();
if (inDoc &&
(mNotificationMask & nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT)) {
GetXTFElement()->WillChangeDocument(nsnull);
}
PRBool parentChanged = aNullParent && GetParent();
if (parentChanged &&
(mNotificationMask & nsIXTFElement::NOTIFY_WILL_CHANGE_PARENT)) {
GetXTFElement()->WillChangeParent(nsnull);
}
nsXTFElementWrapperBase::UnbindFromTree(aDeep, aNullParent);
if (parentChanged &&
(mNotificationMask & nsIXTFElement::NOTIFY_PARENT_CHANGED)) {
GetXTFElement()->ParentChanged(nsnull);
}
if (inDoc &&
(mNotificationMask & nsIXTFElement::NOTIFY_DOCUMENT_CHANGED)) {
GetXTFElement()->DocumentChanged(nsnull);
}
}
nsresult

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

@ -76,9 +76,11 @@ public:
// virtual PRUint32 GetElementType() = 0;
// nsIContent specializations:
void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
void SetParent(nsIContent* aParent);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
PRBool aNotify, PRBool aDeepSetDocument);
nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify,

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

@ -353,10 +353,12 @@ nsXULElement::nsXULElement(nsINodeInfo* aNodeInfo)
nsXULElement::~nsXULElement()
{
//XXX SetDocument(nsnull) is not called always before dtor.
//XXX UnbindFromTree is not called always before dtor.
//XXX Related to templates or overlays?
if (IsInDoc())
SetDocument(nsnull, PR_TRUE, PR_FALSE);
//XXXbz probably related to the cloning thing!
if (IsInDoc()) {
UnbindFromTree();
}
nsDOMSlots* slots = GetExistingDOMSlots();
if (slots) {
@ -512,24 +514,35 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsCOMPtr<nsIContent> result;
// XXX setting document on some nodes not in a document so XBL will bind
// and chrome won't break. Make XBL bind to document-less nodes!
// XXXbz Once this is fixed, fix up the asserts in all implementations of
// BindToTree to assert what they would like to assert, and fix the
// ChangeDocumentFor() call in nsXULElement::BindToTree as well. Also,
// remove the UnbindFromTree call in ~nsXULElement, and add back in the
// precondition in nsXULElement::UnbindFromTree.
// Note: Make sure to do this witchery _after_ we've done any deep
// cloning, so kids of the new node aren't confused about whether they're
// in a document.
PRBool fakeBeingInDocument = PR_TRUE;
// If we have a prototype, so will our clone.
if (mPrototype) {
rv = nsXULElement::Create(mPrototype, GetOwnerDoc(), PR_TRUE,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
if (!IsInDoc()) {
nsIContent* element = result;
NS_STATIC_CAST(nsXULElement*, element)->
mParentPtrBits &= ~PARENT_BIT_INDOCUMENT;
}
// Make sure to unset the "in document" bit we picked up in Create()
// while we create our kids. We'll reset it as needed at the end of
// this function.
NS_STATIC_CAST(nsXULElement*,
NS_STATIC_CAST(nsIContent*, result.get()))->
mParentPtrBits &= ~PARENT_BIT_INDOCUMENT;
fakeBeingInDocument = IsInDoc();
} else {
rv = NS_NewXULElement(getter_AddRefs(result), mNodeInfo);
NS_ENSURE_SUCCESS(rv, rv);
// XXX setting document on nodes not in a document so XBL will bind
// and chrome won't break. Make XBL bind to document-less nodes!
result->SetDocument(GetCurrentDoc(), PR_TRUE, PR_TRUE);
}
// Copy attributes
@ -579,6 +592,14 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
}
}
if (fakeBeingInDocument) {
// Don't use BindToTree here so we don't confuse the descendant
// non-XUL nodes.
NS_STATIC_CAST(nsXULElement*,
NS_STATIC_CAST(nsIContent*, result.get()))->
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
}
return CallQueryInterface(result, aReturn);
}
@ -620,6 +641,8 @@ nsresult
nsXULElement::AddScriptEventListener(nsIAtom* aName, const nsAString& aValue)
{
// XXX sXBL/XBL2 issue! Owner or current document?
// Note that If it's current, then we need to hook up listeners on the root
// when we BindToTree...
nsIDocument* doc = GetOwnerDoc();
if (!doc)
return NS_OK; // XXX
@ -854,102 +877,214 @@ nsXULElement::MaybeAddPopupListener(nsIAtom* aLocalName)
// nsIContent interface
//
void
nsXULElement::SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers)
nsresult
nsXULElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers)
{
nsIDocument* doc = GetCurrentDoc();
if (aDocument != doc) {
if (doc) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
doc->BindingManager()->ChangeDocumentFor(this, doc, aDocument);
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
// 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
// NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
// "aDocument must be current doc of aParent");
NS_PRECONDITION(!aParent ||
(aParent->IsContentOfType(eXUL) && aDocument == nsnull) ||
aDocument == aParent->GetCurrentDoc(),
"aDocument must be current doc of aParent");
// XXXbz we'd like to assert that GetCurrentDoc() is null, but the cloning
// mess makes that impossible. We can't even assert that aDocument ==
// GetCurrentDoc() when GetCurrentDoc() is non-null, since we may be
// getting inserted into a different document. :(
// NS_PRECONDITION(!GetCurrentDoc(),
// "Already have a document. Unbind first!");
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(doc));
nsDoc->SetBoxObjectFor(this, nsnull);
// Note that as we recurse into the kids, they'll have a non-null
// parent. So only assert if our parent is _changing_ while we
// have a parent.
NS_PRECONDITION(!GetParent() || aParent == GetParent(),
"Already have a parent. Unbind first!");
NS_PRECONDITION(!GetBindingParent() ||
aBindingParent == GetBindingParent() ||
(!aBindingParent && aParent &&
aParent->GetBindingParent() == GetBindingParent()),
"Already have a binding parent. Unbind first!");
if (HasProperties()) {
doc->PropertyTable()->DeleteAllPropertiesFor(this);
}
}
if (!aBindingParent && aParent) {
aBindingParent = aParent->GetBindingParent();
}
// mControllers can own objects that are implemented
// in JavaScript (such as some implementations of
// nsIControllers. These objects prevent their global
// object's script object from being garbage collected,
// which means JS continues to hold an owning reference
// to the nsGlobalWindow, which owns the document,
// which owns this content. That's a cycle, so we break
// it here. (It might be better to break this by releasing
// mDocument in nsGlobalWindow::SetDocShell, but I'm not
// sure whether that would fix all possible cycles through
// mControllers.)
nsDOMSlots* slots = GetExistingDOMSlots();
if (!aDocument && slots) {
NS_IF_RELEASE(slots->mControllers); // Forces release
}
// First set the binding parent
mBindingParent = aBindingParent;
// Now set the parent; make sure to preserve the bits we have
// stashed there Note that checking whether aParent == GetParent()
// is probably not worth it here.
PtrBits new_bits = NS_REINTERPRET_CAST(PtrBits, aParent);
new_bits |= mParentPtrBits & nsIContent::kParentBitMask;
mParentPtrBits = new_bits;
if (mListenerManager)
mListenerManager->SetListenerTarget(nsnull);
mListenerManager = nsnull;
// Finally, set the document
if (aDocument && aDocument != GetCurrentDoc()) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
// XXXbz ordering issues here? Probably not, since ChangeDocumentFor
// is just pretty broken anyway.... Need to get it working.
// XXXbz XBL doesn't handle this (asserts), and we don't really want
// to be doing this during parsing anyway... sort this out.
// aDocument->BindingManager()->ChangeDocumentFor(this, nsnull,
// aDocument);
// Being added to a document.
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
if (aDocument) {
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
if (aDocument != mNodeInfo->GetDocument()) {
// get a new nodeinfo
nsNodeInfoManager* nodeInfoManager = aDocument->NodeInfoManager();
if (nodeInfoManager) {
// check the document on the nodeinfo to see whether we need a
// new nodeinfo
// XXXbz sXBL/XBL2 issue!
nsIDocument *ownerDocument = GetOwnerDoc();
if (aDocument != ownerDocument) {
if (HasProperties()) {
ownerDocument->PropertyTable()->DeleteAllPropertiesFor(this);
}
// get a new nodeinfo
nsNodeInfoManager* nodeInfoManager = aDocument->NodeInfoManager();
if (nodeInfoManager) {
nsCOMPtr<nsINodeInfo> newNodeInfo;
nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
mNodeInfo->GetPrefixAtom(),
mNodeInfo->NamespaceID(),
getter_AddRefs(newNodeInfo));
if (newNodeInfo) {
mNodeInfo.swap(newNodeInfo);
}
}
}
// When we SetDocument(), we're either adding an element
// into the document that wasn't there before, or we're
// moving the element from one document to
// another. Regardless, we need to (re-)initialize several
// attributes that are dependant on the document. Do that
// now.
PRInt32 count = mAttrsAndChildren.AttrCount();
PRBool haveLocalAttributes = (count > 0);
PRInt32 i;
for (i = 0; i < count; i++) {
AddListenerFor(*mAttrsAndChildren.GetSafeAttrNameAt(i),
aCompileEventHandlers);
}
if (mPrototype) {
PRInt32 count = mPrototype->mNumAttributes;
for (i = 0; i < count; i++) {
nsXULPrototypeAttribute *protoattr =
&mPrototype->mAttributes[i];
// Don't clobber a locally modified attribute.
if (haveLocalAttributes &&
mAttrsAndChildren.GetAttr(protoattr->mName.LocalName(),
protoattr->mName.NamespaceID())) {
continue;
}
AddListenerFor(protoattr->mName, aCompileEventHandlers);
}
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);
}
}
else {
mParentPtrBits &= ~PARENT_BIT_INDOCUMENT;
// we need to (re-)initialize several attributes that are dependant on
// the document. Do that now.
// XXXbz why do we have attributes depending on the current document?
// Shouldn't they depend on the owner document? Or is this code just
// misplaced, basically?
PRInt32 count = mAttrsAndChildren.AttrCount();
PRBool haveLocalAttributes = (count > 0);
PRInt32 i;
for (i = 0; i < count; i++) {
AddListenerFor(*mAttrsAndChildren.GetSafeAttrNameAt(i),
aCompileEventHandlers);
}
if (mPrototype) {
PRInt32 count = mPrototype->mNumAttributes;
for (i = 0; i < count; i++) {
nsXULPrototypeAttribute *protoattr =
&mPrototype->mAttributes[i];
// Don't clobber a locally modified attribute.
if (haveLocalAttributes &&
mAttrsAndChildren.GetAttr(protoattr->mName.LocalName(),
protoattr->mName.NamespaceID())) {
continue;
}
AddListenerFor(protoattr->mName, aCompileEventHandlers);
}
}
}
// Now recurse into our kids
PRUint32 i, n = GetChildCount();
for (i = 0; i < n; ++i) {
nsresult rv =
mAttrsAndChildren.ChildAt(i)->BindToTree(aDocument, this,
aBindingParent,
aCompileEventHandlers);
NS_ENSURE_SUCCESS(rv, rv);
}
// XXXbz script execution during binding can trigger some of these
// postcondition asserts.... But we do want that, since things will
// generally be quite broken when that happens.
// XXXbz we'd like to assert that we have the right GetCurrentDoc(), but
// we may be being bound to a null document while we already have a
// current doc, due to the cloneNode hack... So can't assert that yet.
// NS_POSTCONDITION(aDocument == GetCurrentDoc(),
// "Bound to wrong document");
NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
NS_POSTCONDITION(aBindingParent == GetBindingParent(),
"Bound to wrong binding parent");
return NS_OK;
}
void
nsXULElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
{
// XXXbz we'd like to assert that called didn't screw up aDeep, but I'm not
// sure we can....
// NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
// "Shallow unbind won't clear document and binding "
// "parent on kids!");
// Make sure to unbind this node before doing the kids
nsIDocument *document = GetCurrentDoc();
if (document) {
// Notify XBL- & nsIAnonymousContentCreator-generated
// anonymous content that the document is changing.
document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(document));
nsDoc->SetBoxObjectFor(this, nsnull);
}
// mControllers can own objects that are implemented
// in JavaScript (such as some implementations of
// nsIControllers. These objects prevent their global
// object's script object from being garbage collected,
// which means JS continues to hold an owning reference
// to the nsGlobalWindow, which owns the document,
// which owns this content. That's a cycle, so we break
// it here. (It might be better to break this by releasing
// mDocument in nsGlobalWindow::SetDocShell, but I'm not
// sure whether that would fix all possible cycles through
// mControllers.)
nsDOMSlots* slots = GetExistingDOMSlots();
if (slots) {
NS_IF_RELEASE(slots->mControllers);
}
// XXXbz why are we nuking our listener manager? We can get events while
// not in a document!
if (mListenerManager) {
mListenerManager->SetListenerTarget(nsnull);
mListenerManager = nsnull;
}
// Unset things in the reverse order from how we set them in BindToTree
mParentPtrBits &= ~PARENT_BIT_INDOCUMENT;
if (aNullParent) {
// Just mask it out
mParentPtrBits &= nsIContent::kParentBitMask;
}
mBindingParent = nsnull;
if (aDeep) {
PRInt32 i;
for (i = mAttrsAndChildren.ChildCount() - 1; i >= 0; --i) {
mAttrsAndChildren.ChildAt(i)->SetDocument(aDocument, aDeep,
aCompileEventHandlers);
// Do the kids. Note that we don't want to GetChildCount(), because
// that will force content generation... if we never had to generate
// the content, we shouldn't force it now!
PRUint32 i, n = PeekChildCount();
for (i = 0; i < n; ++i) {
// Note that we pass PR_FALSE for aNullParent here, since we don't
// want the kids to forget us. We _do_ want them to forget their
// binding parent, though, since this only walks non-anonymous
// kids.
mAttrsAndChildren.ChildAt(i)->UnbindFromTree(PR_TRUE, PR_FALSE);
}
}
}
@ -1014,12 +1149,25 @@ nsXULElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
rv = mAttrsAndChildren.InsertChildAt(aKid, aIndex);
NS_ENSURE_SUCCESS(rv, rv);
aKid->SetParent(this);
rv = aKid->BindToTree(doc, this, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mAttrsAndChildren.RemoveChildAt(aIndex);
aKid->UnbindFromTree();
return rv;
}
// XXXbz this screws up ranges, no? Need to figure out why this is
// commented and uncomment....
//nsRange::OwnerChildInserted(this, aIndex);
if (doc) {
aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE);
// The kid may have removed us from the document, so recheck that we're
// still in the document before proceeding. Also, the kid may have just
// removed itself, in which case we don't really want to fire
// ContentAppended or a mutation event.
// XXXbz What if the kid just moved us in the document? Scripts suck. We
// really need to stop running them while we're in the middle of modifying
// the DOM....
if (doc && doc == GetCurrentDoc() && aKid->GetParent() == this) {
if (aNotify) {
if (isAppend) {
doc->ContentAppended(this, aIndex);
@ -1059,12 +1207,22 @@ nsXULElement::AppendChildTo(nsIContent* aKid, PRBool aNotify,
rv = mAttrsAndChildren.AppendChild(aKid);
NS_ENSURE_SUCCESS(rv, rv);
aKid->SetParent(this);
rv = aKid->BindToTree(doc, this, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
mAttrsAndChildren.RemoveChildAt(GetChildCount() - 1);
aKid->UnbindFromTree();
return rv;
}
// ranges don't need adjustment since new child is at end of list
if (doc) {
aKid->SetDocument(doc, aDeepSetDocument, PR_TRUE);
// The kid may have removed us from the document, so recheck that we're
// still in the document before proceeding. Also, the kid may have just
// removed itself, in which case we don't really want to fire
// ContentAppended or a mutation event.
// XXXbz What if the kid just moved us in the document? Scripts suck. We
// really need to stop running them while we're in the middle of modifying
// the DOM....
if (doc && doc == GetCurrentDoc() && aKid->GetParent() == this) {
if (aNotify) {
doc->ContentAppended(this, mAttrsAndChildren.ChildCount() - 1);
}
@ -1205,10 +1363,7 @@ nsXULElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
// This will cause the script object to be unrooted for each
// element in the subtree.
oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE);
// We've got no mo' parent.
oldKid->SetParent(nsnull);
oldKid->UnbindFromTree();
return NS_OK;
}
@ -2655,22 +2810,6 @@ nsXULElement::GetBindingParent() const
return mBindingParent;
}
nsresult
nsXULElement::SetBindingParent(nsIContent* aParent)
{
nsresult rv = NS_OK;
mBindingParent = aParent; // [Weak] no addref
if (mBindingParent) {
PRUint32 count = GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
rv |= GetChildAt(i)->SetBindingParent(aParent);
}
}
return rv;
}
PRBool
nsXULElement::IsContentOfType(PRUint32 aFlags) const
{

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

@ -461,8 +461,11 @@ public:
NS_DECL_ISUPPORTS_INHERITED
// nsIContent
virtual void SetDocument(nsIDocument* aDocument, PRBool aDeep,
PRBool aCompileEventHandlers);
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
PRBool aCompileEventHandlers);
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual PRBool IsNativeAnonymous() const;
virtual PRUint32 GetChildCount() const;
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
@ -511,7 +514,6 @@ public:
virtual void RemoveFocus(nsPresContext* aPresContext);
virtual nsIContent *GetBindingParent() const;
virtual nsresult SetBindingParent(nsIContent* aParent);
virtual PRBool IsContentOfType(PRUint32 aFlags) const;
virtual nsresult GetListenerManager(nsIEventListenerManager** aResult);
virtual PRBool IsFocusable(PRInt32 *aTabIndex = nsnull);

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

@ -2573,6 +2573,9 @@ nsXULDocument::PrepareToWalk()
rv = CreateElementFromPrototype(proto, getter_AddRefs(root));
if (NS_FAILED(rv)) return rv;
rv = root->BindToTree(this, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) return rv;
SetRootContent(root);
// Add the root element to the XUL document's ID-to-element map.
@ -3545,8 +3548,6 @@ nsXULDocument::CreateElementFromPrototype(nsXULPrototypeElement* aPrototype,
aPrototype->mNodeInfo);
if (NS_FAILED(rv)) return rv;
result->SetDocument(this, PR_FALSE, PR_TRUE);
rv = AddAttributes(aPrototype, result);
if (NS_FAILED(rv)) return rv;
}

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

@ -357,6 +357,7 @@ protected:
/**
* Create a delegate content model element from a prototype.
* Note that the resulting content node is not bound to any tree
*/
nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype,
nsIContent** aResult);

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

@ -1065,13 +1065,12 @@ nsXULContentBuilder::RemoveMember(nsIContent* aContainerElement,
NS_ASSERTION(pos >= 0, "parent doesn't think this child has an index");
if (pos < 0) continue;
// Note: RemoveChildAt sets |child|'s document to null so that
// it'll get knocked out of the XUL doc's resource-to-element
// map.
rv = parent->RemoveChildAt(pos, aNotify);
if (NS_FAILED(rv)) return rv;
// Set its document to null so that it'll get knocked out of
// the XUL doc's resource-to-element map.
child->SetDocument(nsnull, PR_TRUE, PR_TRUE);
// Remove from the content support map.
mContentSupportMap.Remove(child);
@ -1472,8 +1471,6 @@ nsXULContentBuilder::CreateElement(PRInt32 aNameSpaceID,
rv = NS_NewElement(getter_AddRefs(result), aNameSpaceID, nodeInfo);
if (NS_FAILED(rv)) return rv;
result->SetDocument(doc, PR_FALSE, PR_TRUE);
*aResult = result;
NS_ADDREF(*aResult);
return NS_OK;

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

@ -153,9 +153,12 @@ nsHTMLEditor::CreateAnonymousElement(const nsAString & aTag, nsIDOMNode * aPare
// establish parenthood of the element
newContent->SetNativeAnonymous(PR_TRUE);
newContent->SetParent(parentContent);
newContent->SetDocument(doc, PR_TRUE, PR_TRUE);
newContent->SetBindingParent(newContent);
res = newContent->BindToTree(doc, parentContent, newContent, PR_TRUE);
if (NS_FAILED(res)) {
newContent->UnbindFromTree();
return res;
}
// display the element
ps->RecreateFramesFor(newContent);
@ -178,10 +181,8 @@ nsHTMLEditor::DeleteRefToAnonymousNode(nsIDOMElement* aElement,
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (content) {
aDocObserver->ContentRemoved(content->GetCurrentDoc(),
aParentContent, content, -1);
content->SetParent(nsnull);
content->SetBindingParent(nsnull);
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
aParentContent, content, -1);
content->UnbindFromTree();
}
}
}

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

@ -249,7 +249,12 @@ void txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
return;
}
rootContent->SetDocument(doc, PR_FALSE, PR_TRUE);
rv = rootContent->BindToTree(doc, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
NS_ERROR("Failed to bind root to tree");
rootContent->UnbindFromTree();
return rv;
}
doc->SetRootContent(rootContent);

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

@ -296,12 +296,12 @@ void txMozillaXMLOutput::endElement(const nsAString& aName, const PRInt32 aNsID)
// up the tree
// we can't use GetParentNode to check if mCurrentNode is the
// "non-added node" since that does strange things when we've called
// SetDocument manually
// BindToTree manually
if (mCurrentNode == mNonAddedNode) {
nsCOMPtr<nsIDocument> document = do_QueryInterface(mNonAddedParent);
if (document && !mRootContent) {
mRootContent = do_QueryInterface(mCurrentNode);
mRootContent->SetDocument(document, PR_FALSE, PR_TRUE);
mRootContent->BindToTree(document, nsnull, nsnull, PR_TRUE);
document->SetRootContent(mRootContent);
}
else {
@ -455,11 +455,6 @@ void txMozillaXMLOutput::startElement(const nsAString& aName,
ssle->InitStyleLinkElement(nsnull, PR_FALSE);
ssle->SetEnableUpdates(PR_FALSE);
}
nsCOMPtr<nsIContent> cont = do_QueryInterface(element);
NS_ASSERTION(cont, "element doesn't implement nsIContent");
nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
cont->SetDocument(doc, PR_FALSE, PR_TRUE);
}
mParentNode = mCurrentNode;
mCurrentNode = do_QueryInterface(element);
@ -498,7 +493,7 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
mParentNode = wrapper;
mRootContent = do_QueryInterface(wrapper);
mRootContent->SetDocument(document, PR_FALSE, PR_TRUE);
mRootContent->BindToTree(document, nsnull, nsnull, PR_TRUE);
document->SetRootContent(mRootContent);
}
@ -509,7 +504,7 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
else {
if (document && currentElement && !mRootContent) {
mRootContent = do_QueryInterface(mCurrentNode);
mRootContent->SetDocument(document, PR_FALSE, PR_TRUE);
mRootContent->BindToTree(document, nsnull, nsnull, PR_TRUE);
document->SetRootContent(mRootContent);
}
else {

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

@ -712,7 +712,7 @@ txMozillaXSLTProcessor::notifyError()
return;
}
rootContent->SetDocument(document, PR_FALSE, PR_TRUE);
rootContent->BindToTree(document, nsnull, nsnull, PR_TRUE);
document->SetRootContent(rootContent);
nsCOMPtr<nsIDOMText> text;

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

@ -2024,13 +2024,16 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame* aParentFram
// Set aContent as the parent content and set the document object. This
// way event handling works
content->SetParent(aContent);
content->SetDocument(mDocument, PR_TRUE, PR_TRUE);
// Hack the binding parent to make document rules not match (not
// like it matters, since we already have a non-element style
// context... which is totally wacky, but anyway).
rv = content->BindToTree(mDocument, aContent, content, PR_TRUE);
if (NS_FAILED(rv)) {
content->UnbindFromTree();
return rv;
}
content->SetNativeAnonymous(PR_TRUE);
// hack to make document rules not match (not like it matters, since we
// already have a non-element style context... which is totally wacky, but
// anyway).
content->SetBindingParent(content);
// Create an image frame and initialize it
nsIFrame* imageFrame = nsnull;
@ -2086,15 +2089,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame* aParentFram
nsresult rv = NS_ERROR_FAILURE;
if (attrName) {
nsIFrame* textFrame = nsnull;
rv = NS_NewAttributeContent(aContent, attrNameSpace, attrName,
rv = NS_NewAttributeContent(attrNameSpace, attrName,
getter_AddRefs(content));
NS_ENSURE_SUCCESS(rv, rv);
// Set aContent as the parent content so that event handling works.
content->SetParent(aContent);
content->SetDocument(mDocument, PR_TRUE, PR_TRUE);
rv = content->BindToTree(mDocument, aContent, content, PR_TRUE);
if (NS_FAILED(rv)) {
content->UnbindFromTree();
return rv;
}
content->SetNativeAnonymous(PR_TRUE);
content->SetBindingParent(content);
// Create a text frame and initialize it
NS_NewTextFrame(mPresShell, &textFrame);
@ -2182,10 +2188,14 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame* aParentFram
}
// Set aContent as the parent content so that event handling works.
textContent->SetParent(aContent);
textContent->SetDocument(mDocument, PR_TRUE, PR_TRUE);
nsresult rv = textContent->BindToTree(mDocument, aContent, textContent,
PR_TRUE);
if (NS_FAILED(rv)) {
textContent->UnbindFromTree();
return rv;
}
textContent->SetNativeAnonymous(PR_TRUE);
textContent->SetBindingParent(textContent);
// Create a text frame and initialize it
NS_NewTextFrame(mPresShell, &textFrame);
@ -5615,10 +5625,9 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
continue;
content->SetNativeAnonymous(PR_TRUE);
content->SetParent(aParent);
content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
nsresult rv;
nsIContent* bindingParent = content;
#ifdef MOZ_XUL
// Only cut XUL scrollbars off if they're not in a XUL document.
// This allows scrollbars to be styled from XUL (although not
@ -5629,15 +5638,13 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
ni->Equals(nsXULAtoms::scrollcorner, kNameSpaceID_XUL))) {
nsCOMPtr<nsIDOMXULDocument> xulDoc(do_QueryInterface(aDocument));
if (xulDoc)
rv = content->SetBindingParent(aParent);
else
rv = content->SetBindingParent(content);
bindingParent = aParent;
}
else
#endif
#ifdef MOZ_XTF
if (aForceBindingParent)
rv = content->SetBindingParent(aParent);
bindingParent = aParent;
else
#endif
#ifdef MOZ_SVG
@ -5646,12 +5653,14 @@ nsCSSFrameConstructor::CreateAnonymousFrames(nsFrameConstructorState& aState,
if (aParent &&
aParent->GetNodeInfo() &&
aParent->GetNodeInfo()->Equals(nsSVGAtoms::use, kNameSpaceID_SVG))
rv = content->SetBindingParent(aParent);
else
bindingParent = aParent;
#endif
rv = content->SetBindingParent(content);
NS_ENSURE_SUCCESS(rv, rv);
rv = content->BindToTree(aDocument, aParent, bindingParent, PR_TRUE);
if (NS_FAILED(rv)) {
content->UnbindFromTree();
return rv;
}
nsIFrame * newFrame = nsnull;
rv = creator->CreateFrameFor(aState.mPresContext, content, &newFrame);
@ -10484,8 +10493,14 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIContent* aContent,
altTextContent->SetText(altText, PR_TRUE);
// Set aContent as the parent content.
altTextContent->SetParent(aContent);
altTextContent->SetDocument(mDocument, PR_TRUE, PR_TRUE);
// XXXbz should this set the binding parent to |altTextContent|?
rv = altTextContent->BindToTree(mDocument, aContent, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
altTextContent->UnbindFromTree();
return rv;
}
// XXXbz shouldn't it be set native anonymous too?
// Create either an inline frame, block frame, or area frame
nsIFrame* containerFrame;

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

@ -4904,7 +4904,7 @@ PresShell::SetAnonymousContentFor(nsIContent* aContent, nsISupportsArray* aAnony
if (! content)
continue;
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
content->UnbindFromTree();
}
}
}
@ -4943,7 +4943,7 @@ ClearDocumentEnumerator(nsHashKey* aKey, void* aData, void* aClosure)
if (! content)
continue;
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
content->UnbindFromTree();
}
return PR_TRUE;

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

@ -362,15 +362,20 @@ nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup, nsIDocument **aDocum
// blat in the structure
if (htmlElement && headElement && bodyElement) {
htmlElement->SetDocument(blankDoc, PR_FALSE, PR_TRUE);
blankDoc->SetRootContent(htmlElement);
rv = htmlElement->BindToTree(blankDoc, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
htmlElement->UnbindFromTree();
} else {
blankDoc->SetRootContent(htmlElement);
htmlElement->AppendChildTo(headElement, PR_FALSE, PR_FALSE);
htmlElement->AppendChildTo(headElement, PR_FALSE, PR_FALSE);
bodyElement->SetContentID(blankDoc->GetAndIncrementContentID());
htmlElement->AppendChildTo(bodyElement, PR_FALSE, PR_FALSE);
bodyElement->SetContentID(blankDoc->GetAndIncrementContentID());
// XXXbz Why not notifying here?
htmlElement->AppendChildTo(bodyElement, PR_FALSE, PR_FALSE);
rv = NS_OK;
rv = NS_OK;
}
}
}

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

@ -130,8 +130,7 @@ CleanupGeneratedContentIn(nsIContent* aRealContent, nsIFrame* aRoot) {
while (child) {
nsIContent* content = child->GetContent();
if (content && content != aRealContent) {
content->SetParent(nsnull);
content->SetDocument(nsnull, PR_TRUE, PR_TRUE);
content->UnbindFromTree();
}
::CleanupGeneratedContentIn(aRealContent, child);
child = child->GetNextSibling();

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

@ -89,8 +89,8 @@ NS_NewBlockFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame,
// Special Generated Content Frame
nsresult
NS_NewAttributeContent(nsIContent* aContent, PRInt32 aNameSpaceID,
nsIAtom* aAttrName, nsIContent** aResult);
NS_NewAttributeContent(PRInt32 aNameSpaceID, nsIAtom* aAttrName,
nsIContent** aResult);
// Create a basic area frame but the GetFrameForPoint is overridden to always
// return the option frame

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

@ -1564,9 +1564,13 @@ nsObjectFrame::CreateDefaultFrames(nsPresContext *aPresContext,
img->SetNativeAnonymous(PR_TRUE);
text->SetNativeAnonymous(PR_TRUE);
// Set up the anonymous tree
anchor->SetParent(mContent);
anchor->SetDocument(doc, PR_TRUE, PR_TRUE);
// Set up the anonymous tree. Note that the binding parent for the anchor is
// used to cut off style rules from the page so they won't apply to it.
rv = anchor->BindToTree(doc, mContent, anchor, PR_TRUE);
if (NS_FAILED(rv)) {
anchor->UnbindFromTree();
return rv;
}
anchor->AppendChildTo(img, PR_FALSE, PR_TRUE);
anchor->AppendChildTo(text, PR_FALSE, PR_TRUE);

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

@ -263,7 +263,12 @@ int main(int argc, char** argv)
txt->AppendData(tmp);
NS_RELEASE(txt);
text->SetDocument(myDoc, PR_FALSE, PR_TRUE);
rv = text->BindToTree(myDoc, nsnull, nsnull, PR_FALSE);
if (NS_FAILED(rv)) {
printf("Could not bind text content to tree.\n");
text->UnbindFromTree();
return -1;
}
#if 0
// Query ITextContent interface