зеркало из https://github.com/mozilla/gecko-dev.git
Implement an nsINode interface; move some common stuff from nsIContent and
nsIDocument to nsINode. Bug 323311, r=sicking, sr=jst
This commit is contained in:
Родитель
7105c7c96d
Коммит
b64fcb4a39
|
@ -58,6 +58,7 @@ nsIDocumentEncoder.h \
|
|||
nsIDocumentObserver.h \
|
||||
nsIDOMGCParticipant.h \
|
||||
nsINameSpaceManager.h \
|
||||
nsINode.h \
|
||||
nsINodeInfo.h \
|
||||
nsIRangeUtils.h \
|
||||
nsIScriptElement.h \
|
||||
|
|
|
@ -46,11 +46,7 @@
|
|||
#include "nsPropertyTable.h"
|
||||
#include "nsCaseTreatment.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsIDOMGCParticipant.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "nsINodeInfo.h"
|
||||
#endif
|
||||
#include "nsINode.h"
|
||||
|
||||
// Forward declarations
|
||||
class nsIAtom;
|
||||
|
@ -69,16 +65,16 @@ class nsAttrValue;
|
|||
class nsAttrName;
|
||||
|
||||
// IID for the nsIContent interface
|
||||
// ffc6f2b8-bcdc-4cf7-b72f-e843860f14a6
|
||||
// e7c1214f-8164-43aa-934e-b8b06431a93d
|
||||
#define NS_ICONTENT_IID \
|
||||
{ 0xe616c36e, 0x7db7, 0x46b0, \
|
||||
{ 0x89, 0x11, 0xf5, 0xd1, 0x74, 0xfa, 0x37, 0x34 } }
|
||||
{ 0xe7c1214f, 0x8164, 0x43aa, \
|
||||
{ 0x93, 0x4e, 0xb8, 0xb0, 0x64, 0x31, 0xa9, 0x3d } }
|
||||
|
||||
/**
|
||||
* A node of content in a document's content model. This interface
|
||||
* is supported by all content objects.
|
||||
*/
|
||||
class nsIContent : public nsIDOMGCParticipant {
|
||||
class nsIContent : public nsINode {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENT_IID)
|
||||
|
||||
|
@ -87,8 +83,8 @@ public:
|
|||
// nsIContent is that it exists with an IID
|
||||
|
||||
nsIContent(nsINodeInfo *aNodeInfo)
|
||||
: mParentPtrBits(0),
|
||||
mNodeInfo(aNodeInfo)
|
||||
: nsINode(aNodeInfo),
|
||||
mParentPtrBits(0)
|
||||
{
|
||||
NS_ASSERTION(aNodeInfo,
|
||||
"No nsINodeInfo passed to nsIContent, PREPARE TO CRASH!!!");
|
||||
|
@ -171,16 +167,6 @@ public:
|
|||
return IsInDoc() ? GetOwnerDoc() : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ownerDocument for this content.
|
||||
*
|
||||
* @return the ownerDocument
|
||||
*/
|
||||
nsIDocument *GetOwnerDoc() const
|
||||
{
|
||||
return mNodeInfo->GetDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent content for this content.
|
||||
* @return the parent, or null if no parent
|
||||
|
@ -231,57 +217,6 @@ public:
|
|||
return mNodeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of children
|
||||
* @return the number of children
|
||||
*/
|
||||
virtual PRUint32 GetChildCount() const = 0;
|
||||
|
||||
/**
|
||||
* Get a child by index
|
||||
* @param aIndex the index of the child to get, or null if index out
|
||||
* of bounds
|
||||
* @return the child
|
||||
*/
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const = 0;
|
||||
|
||||
/**
|
||||
* Get the index of a child within this content
|
||||
* @param aPossibleChild the child to get the index
|
||||
* @return the index of the child, or -1 if not a child
|
||||
*/
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const = 0;
|
||||
|
||||
/**
|
||||
* Insert a content node at a particular index.
|
||||
*
|
||||
* @param aKid the content to insert
|
||||
* @param aIndex the index it is being inserted at (the index it will have
|
||||
* after it is inserted)
|
||||
* @param aNotify whether to notify the document that the insert has
|
||||
* occurred
|
||||
*/
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Append a content node to the end of the child list.
|
||||
*
|
||||
* @param aKid the content to append
|
||||
* @param aNotify whether to notify the document that the replace has
|
||||
* occurred
|
||||
*/
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Remove a child from this content node.
|
||||
*
|
||||
* @param aIndex the index of the child to remove
|
||||
* @param aNotify whether to notify the document that the replace has
|
||||
* occurred
|
||||
*/
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Returns an atom holding the name of the attribute of type ID on
|
||||
* this content node (if applicable). Returns null for non-element
|
||||
|
@ -916,8 +851,6 @@ protected:
|
|||
|
||||
PtrBits mParentPtrBits;
|
||||
|
||||
nsCOMPtr<nsINodeInfo> mNodeInfo;
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
};
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#ifndef nsIDocument_h___
|
||||
#define nsIDocument_h___
|
||||
|
||||
#include "nsIDOMGCParticipant.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
@ -92,10 +92,10 @@ class nsIVariant;
|
|||
class nsIDOMUserDataHandler;
|
||||
|
||||
// IID for the nsIDocument interface
|
||||
// a5d8343d-9b0a-40a8-a47e-893065749f0b
|
||||
// 1e787f0e-feb3-43e3-bd00-bf8a77dcc557
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xa5d8343d, 0x9b0a, 0x40a8, \
|
||||
{ 0xa4, 0x7e, 0x89, 0x30, 0x65, 0x74, 0x9f, 0x0b } }
|
||||
{ 0x1e787f0e, 0xfeb3, 0x43e3, \
|
||||
{ 0xbd, 0x00, 0xbf, 0x8a, 0x77, 0xdc, 0xc5, 0x57 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
|
@ -104,18 +104,21 @@ class nsIDOMUserDataHandler;
|
|||
|
||||
// Document interface. This is implemented by all document objects in
|
||||
// Gecko.
|
||||
class nsIDocument : public nsIDOMGCParticipant
|
||||
class nsIDocument : public nsINode
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
|
||||
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsIDocument()
|
||||
: mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
|
||||
: nsINode(nsnull),
|
||||
mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
|
||||
mNodeInfoManager(nsnull),
|
||||
mPartID(0)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Let the document know that we're starting to load data into it.
|
||||
|
@ -372,26 +375,6 @@ public:
|
|||
return mRootContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set aRoot as the root content object for this document. If aRoot is
|
||||
* non-null, this should not be called on documents that currently have a
|
||||
* root content without first clearing out the document's children. Passing
|
||||
* in null to unbind the existing root content is allowed. This method will
|
||||
* bind aRoot to the document; the caller need not call BindToTree on aRoot.
|
||||
*
|
||||
* Note that this method never sends out nsIDocumentObserver notifications;
|
||||
* doing that is the caller's responsibility.
|
||||
*/
|
||||
virtual nsresult SetRootContent(nsIContent* aRoot) = 0;
|
||||
|
||||
/**
|
||||
* Get the direct children of the document - content in
|
||||
* the prolog, the root content and content in the epilog.
|
||||
*/
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const = 0;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const = 0;
|
||||
virtual PRUint32 GetChildCount() const = 0;
|
||||
|
||||
/**
|
||||
* Accessors to the collection of stylesheets owned by this document.
|
||||
* Style sheets are ordered, most significant last.
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla.com.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Boris Zbarsky <bzbarsky@mit.edu> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsINode_h___
|
||||
#define nsINode_h___
|
||||
|
||||
#include "nsIDOMGCParticipant.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "nsINodeInfo.h"
|
||||
#endif
|
||||
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
|
||||
// IID for the nsINode interface
|
||||
// a22b59d9-cc21-402c-bdd2-2780e4cd5883
|
||||
#define NS_INODE_IID \
|
||||
{ 0xa22b59d9, 0xcc21, 0x402c, \
|
||||
{ 0xbd, 0xd2, 0x27, 0x80, 0xe4, 0xcd, 0x58, 0x83 } }
|
||||
|
||||
/**
|
||||
* An internal interface that abstracts some DOMNode-related parts that both
|
||||
* nsIContent and nsIDocument share. An instance of this interface has a list
|
||||
* of nsIContent children and provides access to them.
|
||||
*/
|
||||
class nsINode : public nsIDOMGCParticipant {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// If you're using the external API, the only thing you can know about
|
||||
// nsINode is that it exists with an IID, if that....
|
||||
|
||||
nsINode(nsINodeInfo* aNodeInfo)
|
||||
: mNodeInfo(aNodeInfo)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of children
|
||||
* @return the number of children
|
||||
*/
|
||||
virtual PRUint32 GetChildCount() const = 0;
|
||||
|
||||
/**
|
||||
* Get a child by index
|
||||
* @param aIndex the index of the child to get
|
||||
* @return the child, or null if index out of bounds
|
||||
*/
|
||||
virtual nsIContent* GetChildAt(PRUint32 aIndex) const = 0;
|
||||
|
||||
/**
|
||||
* Get the index of a child within this content
|
||||
* @param aPossibleChild the child to get the index of.
|
||||
* @return the index of the child, or -1 if not a child
|
||||
*
|
||||
* If the return value is not -1, then calling GetChildAt() with that value
|
||||
* will return aPossibleChild.
|
||||
*/
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const = 0;
|
||||
|
||||
/**
|
||||
* Do we need a GetCurrentDoc of some sort? I don't think we do...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return the "owner document" of this node. Note that this is not the same
|
||||
* as the DOM ownerDocument -- that's null for Document nodes, whereas for a
|
||||
* nsIDocument GetOwnerDocument returns the document itself. For nsIContent
|
||||
* implementations the two are the same.
|
||||
*/
|
||||
nsIDocument *GetOwnerDoc() const
|
||||
{
|
||||
return mNodeInfo->GetDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a content node at a particular index. This method handles calling
|
||||
* BindToTree on the child appropriately.
|
||||
*
|
||||
* @param aKid the content to insert
|
||||
* @param aIndex the index it is being inserted at (the index it will have
|
||||
* after it is inserted)
|
||||
* @param aNotify whether to notify the document (current document for
|
||||
* nsIContent, and |this| for nsIDocument) that the insert has
|
||||
* occurred
|
||||
*
|
||||
* @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
|
||||
* than one element node as a child of a document. Doing this will also
|
||||
* assert -- you shouldn't be doing it! Check with
|
||||
* nsIDocument::GetRootContent() first if you're not sure. Apart from this
|
||||
* one constraint, this doesn't do any checking on whether aKid is a valid
|
||||
* child of |this|.
|
||||
*
|
||||
* @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
|
||||
*/
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Append a content node to the end of the child list. This method handles
|
||||
* calling BindToTree on the child appropriately.
|
||||
*
|
||||
* @param aKid the content to append
|
||||
* @param aNotify whether to notify the document (current document for
|
||||
* nsIContent, and |this| for nsIDocument) that the append has
|
||||
* occurred
|
||||
*
|
||||
* @throws NS_ERROR_DOM_HIERARCHY_REQUEST_ERR if one attempts to have more
|
||||
* than one element node as a child of a document. Doing this will also
|
||||
* assert -- you shouldn't be doing it! Check with
|
||||
* nsIDocument::GetRootContent() first if you're not sure. Apart from this
|
||||
* one constraint, this doesn't do any checking on whether aKid is a valid
|
||||
* child of |this|.
|
||||
*
|
||||
* @throws NS_ERROR_OUT_OF_MEMORY in some cases (from BindToTree).
|
||||
*/
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* Remove a child from this node. This method handles calling UnbindFromTree
|
||||
* on the child appropriately.
|
||||
*
|
||||
* @param aIndex the index of the child to remove
|
||||
* @param aNotify whether to notify the document (current document for
|
||||
* nsIContent, and |this| for nsIDocument) that the remove has
|
||||
* occurred
|
||||
*
|
||||
* Note: If there is no child at aIndex, this method will simply do nothing.
|
||||
*/
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify) = 0;
|
||||
|
||||
/**
|
||||
* IsNodeOfType()? Do we need a non-QI way to tell apart documents and
|
||||
* content?
|
||||
*/
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsINodeInfo> mNodeInfo;
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsINode, NS_INODE_IID)
|
||||
|
||||
#endif /* nsINode_h___ */
|
|
@ -125,6 +125,7 @@ NS_INTERFACE_MAP_BEGIN(nsDOMDocumentType)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMDocumentType)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
|
||||
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this))
|
||||
NS_INTERFACE_MAP_ENTRY(nsINode)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(DocumentType)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
|
|
@ -830,6 +830,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocument)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOM3Document)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRadioGroupContainer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsINode)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocument)
|
||||
if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) ||
|
||||
aIID.Equals(NS_GET_IID(nsIXPathEvaluatorInternal))) {
|
||||
|
@ -881,7 +882,15 @@ nsDocument::Init()
|
|||
|
||||
NS_ADDREF(mNodeInfoManager);
|
||||
|
||||
return mNodeInfoManager->Init(this);
|
||||
nsresult rv = mNodeInfoManager->Init(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
|
||||
NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
NS_ASSERTION(GetOwnerDoc() == this, "Our nodeinfo is busted!");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1672,40 +1681,6 @@ nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
|
|||
return data.mResult;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::SetRootContent(nsIContent* aRoot)
|
||||
{
|
||||
if (aRoot) {
|
||||
NS_ASSERTION(!mRootContent,
|
||||
"Already have a root content! Clear out first!");
|
||||
nsresult rv = aRoot->BindToTree(this, nsnull, nsnull, PR_TRUE);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mChildren.AppendChild(aRoot);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
aRoot->UnbindFromTree();
|
||||
} else {
|
||||
mRootContent = aRoot;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mRootContent) {
|
||||
DestroyLinkMap();
|
||||
mRootContent->UnbindFromTree();
|
||||
PRInt32 pos = mChildren.IndexOfChild(mRootContent);
|
||||
if (pos >= 0) {
|
||||
mChildren.RemoveChildAt(pos);
|
||||
}
|
||||
mRootContent = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent *
|
||||
nsDocument::GetChildAt(PRUint32 aIndex) const
|
||||
{
|
||||
|
@ -1724,6 +1699,110 @@ nsDocument::GetChildCount() const
|
|||
return mChildren.ChildCount();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (aKid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
if (mRootContent) {
|
||||
NS_ERROR("Inserting element child when we already have one");
|
||||
return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
|
||||
}
|
||||
|
||||
mRootContent = aKid;
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericElement::doInsertChildAt(aKid, aIndex, aNotify,
|
||||
nsnull, this, mChildren);
|
||||
|
||||
if (NS_FAILED(rv) && mRootContent == aKid) {
|
||||
PRInt32 kidIndex = mChildren.IndexOfChild(aKid);
|
||||
NS_ASSERTION(kidIndex == -1,
|
||||
"Error result and still have same root content but it's in "
|
||||
"our child list?");
|
||||
// Check to make sure that we're keeping mRootContent in sync with our
|
||||
// child list... but really, if kidIndex != -1 we have major problems
|
||||
// coming up; hence the assert above. This check is just a feeble attempt
|
||||
// to not die due to mRootContent being bogus.
|
||||
if (kidIndex == -1) {
|
||||
mRootContent = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
VerifyRootContentState();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
||||
{
|
||||
// Make sure to _not_ call the subclass InsertChildAt here. If
|
||||
// subclasses wanted to hook into this stuff, they would have
|
||||
// overridden AppendChildTo.
|
||||
// XXXbz maybe this should just be a non-virtual method on nsINode?
|
||||
// Feels that way to me...
|
||||
return nsDocument::InsertChildAt(aKid, GetChildCount(), aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
||||
{
|
||||
nsCOMPtr<nsIContent> oldKid = GetChildAt(aIndex);
|
||||
nsresult rv = NS_OK;
|
||||
if (oldKid) {
|
||||
if (oldKid == mRootContent) {
|
||||
NS_ASSERTION(oldKid->IsContentOfType(nsIContent::eELEMENT),
|
||||
"Non-element root content?");
|
||||
// Destroy the link map up front and null out mRootContent before we mess
|
||||
// with the child list. Hopefully no one in doRemoveChildAt will compare
|
||||
// the content being removed to GetRootContent().... Need to do this
|
||||
// before calling doRemoveChildAt because DOM events might fire while
|
||||
// we're inside the doInsertChildAt call and want to set a new
|
||||
// mRootContent; if they do that, setting mRootContent after the
|
||||
// doRemoveChildAt call would clobber state. If we ever fix the issue of
|
||||
// DOM events firing at inconvenient times, consider changing the order
|
||||
// here. Just make sure we DestroyLinkMap() before unbinding the
|
||||
// content.
|
||||
DestroyLinkMap();
|
||||
mRootContent = nsnull;
|
||||
}
|
||||
|
||||
rv = nsGenericElement::doRemoveChildAt(aIndex, aNotify, oldKid,
|
||||
nsnull, this, mChildren);
|
||||
if (NS_FAILED(rv) && mChildren.IndexOfChild(oldKid) != -1) {
|
||||
mRootContent = oldKid;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
VerifyRootContentState();
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
nsDocument::VerifyRootContentState()
|
||||
{
|
||||
nsIContent* elementChild = nsnull;
|
||||
for (PRUint32 i = 0; i < GetChildCount(); ++i) {
|
||||
nsIContent* kid = GetChildAt(i);
|
||||
NS_ASSERTION(kid, "Must have kid here");
|
||||
|
||||
if (kid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
NS_ASSERTION(!elementChild, "Multiple element kids?");
|
||||
elementChild = kid;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(mRootContent == elementChild, "Incorrect mRootContent");
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
PRInt32
|
||||
nsDocument::GetNumberOfStyleSheets() const
|
||||
{
|
||||
|
@ -3581,7 +3660,7 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
nsIDOMNode** aReturn)
|
||||
{
|
||||
return nsGenericElement::doInsertBefore(aNewChild, aRefChild, nsnull, this,
|
||||
mChildren, aReturn);
|
||||
aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3589,20 +3668,19 @@ nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
nsIDOMNode** aReturn)
|
||||
{
|
||||
return nsGenericElement::doReplaceChild(aNewChild, aOldChild, nsnull, this,
|
||||
mChildren, aReturn);
|
||||
aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn)
|
||||
{
|
||||
return nsGenericElement::doRemoveChild(aOldChild, nsnull, this,
|
||||
mChildren, aReturn);
|
||||
return nsGenericElement::doRemoveChild(aOldChild, nsnull, this, aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
|
||||
{
|
||||
return InsertBefore(aNewChild, nsnull, aReturn);
|
||||
return nsDocument::InsertBefore(aNewChild, nsnull, aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -388,16 +388,6 @@ public:
|
|||
virtual nsIDocument* GetSubDocumentFor(nsIContent *aContent) const;
|
||||
virtual nsIContent* FindContentForSubDocument(nsIDocument *aDocument) const;
|
||||
|
||||
virtual nsresult SetRootContent(nsIContent* aRoot);
|
||||
|
||||
/**
|
||||
* Get the direct children of the document - content in
|
||||
* the prolog, the root content and content in the epilog.
|
||||
*/
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
|
||||
/**
|
||||
* Get the style sheets owned by this document.
|
||||
* These are ordered, highest priority last
|
||||
|
@ -534,6 +524,15 @@ public:
|
|||
virtual void OnPageShow(PRBool aPersisted);
|
||||
virtual void OnPageHide(PRBool aPersisted);
|
||||
|
||||
// nsINode
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
|
||||
// nsIRadioGroupContainer
|
||||
NS_IMETHOD WalkRadioGroup(const nsAString& aName,
|
||||
nsIRadioVisitor* aVisitor);
|
||||
|
@ -715,6 +714,10 @@ protected:
|
|||
// Dispatch an event to the ScriptGlobalObject for this document
|
||||
void DispatchEventToWindow(nsEvent *aEvent);
|
||||
|
||||
#ifdef DEBUG
|
||||
void VerifyRootContentState();
|
||||
#endif
|
||||
|
||||
nsDocument();
|
||||
virtual ~nsDocument();
|
||||
|
||||
|
|
|
@ -207,6 +207,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocumentFragment)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMNode)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOM3Node)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIContent)
|
||||
NS_INTERFACE_MAP_ENTRY(nsINode)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
|
||||
NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(DocumentFragment)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
|
|
@ -106,6 +106,7 @@ NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIContent)
|
||||
// No nsITextContent since all subclasses might not want that.
|
||||
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this))
|
||||
NS_INTERFACE_MAP_ENTRY(nsINode)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
||||
|
|
|
@ -178,6 +178,15 @@ public:
|
|||
virtual nsIDOMGCParticipant* GetSCCIndex();
|
||||
virtual void AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray);
|
||||
|
||||
// nsINode methods
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
|
||||
// Implementation for nsIContent
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
|
@ -222,13 +231,6 @@ public:
|
|||
virtual nsresult GetListenerManager(nsIEventListenerManager **aResult);
|
||||
virtual already_AddRefed<nsIURI> GetBaseURI() const;
|
||||
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
virtual PRBool MayHaveFrame() const;
|
||||
virtual void SetHasProperties()
|
||||
{
|
||||
|
|
|
@ -108,45 +108,6 @@
|
|||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsIDOMUserDataHandler.h"
|
||||
|
||||
|
||||
/**
|
||||
* Most of the implementation of the nsIContent InsertChildAt method. Shared
|
||||
* by nsDocument for insertions via DOM methods. When called from
|
||||
* nsDocument, aParent will be null.
|
||||
*
|
||||
* @param aKid The child to insert.
|
||||
* @param aIndex The index to insert at.
|
||||
* @param aNotify Whether to notify.
|
||||
* @param aParent The parent to use for the new child.
|
||||
* @param aDocument The document to use for the new child.
|
||||
* Must be non-null if aParent is null and must match
|
||||
* aParent->GetCurrentDoc() if aParent is not null.
|
||||
* @param aChildArray The child array to work with
|
||||
*/
|
||||
static nsresult
|
||||
doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray);
|
||||
|
||||
/**
|
||||
* Most of the implementation of the nsIContent RemoveChildAt method. Shared
|
||||
* by nsDocument for removals via DOM methods, sometimes. When called from
|
||||
* nsDocument, aParent will be null.
|
||||
*
|
||||
* @param aIndex The index to remove at.
|
||||
* @param aNotify Whether to notify.
|
||||
* @param aKid The kid at aIndex. Must not be null.
|
||||
* @param aParent The parent we're removing from.
|
||||
* @param aDocument The document we're removing from.
|
||||
* Must be non-null if aParent is null and must match
|
||||
* aParent->GetCurrentDoc() if aParent is not null.
|
||||
* @param aChildArray The child array to work with
|
||||
*/
|
||||
static nsresult
|
||||
doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray);
|
||||
|
||||
#ifdef MOZ_SVG
|
||||
PRBool NS_SVG_TestFeature(const nsAString &fstr);
|
||||
#endif /* MOZ_SVG */
|
||||
|
@ -2711,25 +2672,21 @@ nsGenericElement::InsertChildAt(nsIContent* aKid,
|
|||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
/* static */
|
||||
nsresult
|
||||
nsGenericElement::doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify, nsIContent* aParent,
|
||||
nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
|
||||
"Incorrect aDocument");
|
||||
|
||||
PRBool isAppend = (aIndex == aChildArray.ChildCount());
|
||||
|
||||
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
// Note that SetRootContent already deals with binding, so if we plan to call
|
||||
// it we shouldn't bind ourselves.
|
||||
// XXXbz this doesn't put aKid in the right spot, really... We really need a
|
||||
// better api for handling kids on documents.
|
||||
if (!aParent && aKid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
nsresult rv = aDocument->SetRootContent(aKid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
nsresult rv = aChildArray.InsertChildAt(aKid, aIndex);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -2739,9 +2696,9 @@ doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
|||
aKid->UnbindFromTree();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (aParent) {
|
||||
// Adjust ranges, but only if we're not appending to the end of the list
|
||||
if (aParent && !isAppend) {
|
||||
nsRange::OwnerChildInserted(aParent, aIndex);
|
||||
}
|
||||
|
||||
|
@ -2757,7 +2714,7 @@ doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
|||
if (aNotify) {
|
||||
// Note that we always want to call ContentInserted when things are added
|
||||
// as kids to documents
|
||||
if (aParent && aIndex == aParent->GetChildCount() - 1) {
|
||||
if (aParent && isAppend) {
|
||||
aDocument->ContentAppended(aParent, aIndex);
|
||||
} else {
|
||||
aDocument->ContentInserted(aParent, aKid, aIndex);
|
||||
|
@ -2767,8 +2724,7 @@ doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
|||
// XXXbz how come we're not firing mutation listeners for adding to
|
||||
// documents?
|
||||
if (aParent &&
|
||||
nsGenericElement::HasMutationListeners(aParent,
|
||||
NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
HasMutationListeners(aParent, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED, aKid);
|
||||
mutation.mRelatedNode = do_QueryInterface(aParent);
|
||||
|
||||
|
@ -2783,47 +2739,12 @@ doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
|||
nsresult
|
||||
nsGenericElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(aKid && this != aKid, "null ptr");
|
||||
|
||||
nsresult rv = WillAddOrRemoveChild(aKid, GetChildCount(), PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIDocument *document = GetCurrentDoc();
|
||||
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
rv = mAttrsAndChildren.AppendChild(aKid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
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
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (HasMutationListeners(this, NS_EVENT_BITS_MUTATION_NODEINSERTED)) {
|
||||
nsMutationEvent mutation(PR_TRUE, NS_MUTATION_NODEINSERTED, aKid);
|
||||
mutation.mRelatedNode = do_QueryInterface(this);
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
aKid->HandleDOMEvent(nsnull, &mutation, nsnull, NS_EVENT_FLAG_INIT, &status);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
// Make sure to _not_ call the subclass InsertChildAt here. If
|
||||
// subclasses wanted to hook into this stuff, they would have
|
||||
// overridden AppendChildTo.
|
||||
// XXXbz maybe this should just be a non-virtual method on nsINode?
|
||||
// Feels that way to me...
|
||||
return nsGenericElement::InsertChildAt(aKid, GetChildCount(), aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -2841,84 +2762,24 @@ nsGenericElement::RemoveChildAt(PRUint32 aIndex, PRBool aNotify)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Note: A lot of methods like IndexOf(), GetChildCount(), etc, need to do more
|
||||
// than just look at the child array for some subclasses, so make sure to call
|
||||
// them instead of just messing with aChildArray
|
||||
struct nsContentOrDocument {
|
||||
nsContentOrDocument(nsIContent* aContent, nsIDocument* aDocument) :
|
||||
mContent(aContent), mDocument(aDocument)
|
||||
{}
|
||||
|
||||
PRInt32 IndexOf(nsIContent* aPossibleChild)
|
||||
{
|
||||
return mContent ? mContent->IndexOf(aPossibleChild) :
|
||||
mDocument->IndexOf(aPossibleChild);
|
||||
}
|
||||
|
||||
PRUint32 GetChildCount()
|
||||
{
|
||||
return mContent ? mContent->GetChildCount() :
|
||||
mDocument->GetChildCount();
|
||||
}
|
||||
|
||||
nsIContent* GetChildAt(PRUint32 aIndex)
|
||||
{
|
||||
return mContent ? mContent->GetChildAt(aIndex) :
|
||||
mDocument->GetChildAt(aIndex);
|
||||
}
|
||||
|
||||
nsIDocument* GetOwnerDoc()
|
||||
{
|
||||
return mContent ? mContent->GetOwnerDoc() : mDocument;
|
||||
}
|
||||
|
||||
nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
|
||||
nsAttrAndChildArray& aChildArray)
|
||||
{
|
||||
// XXXbz can't quite use doInsertChildAt because InsertChildAt has this
|
||||
// random subclass notification it now does... and because subclasses
|
||||
// might be intercepting InsertChildAt and doing stuff.
|
||||
return mContent ? mContent->InsertChildAt(aKid, aIndex, aNotify) :
|
||||
doInsertChildAt(aKid, aIndex, aNotify, mContent, mDocument, aChildArray);
|
||||
}
|
||||
|
||||
nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
||||
nsAttrAndChildArray& aChildArray)
|
||||
{
|
||||
// XXXbz can't quite use doRemoveChildAt because RemoveChildAt has this
|
||||
// random subclass notification it now does... and because subclasses
|
||||
// might be intercepting RemoveChildAt and doing stuff.
|
||||
if (mContent) {
|
||||
return mContent->RemoveChildAt(aIndex, aNotify);
|
||||
}
|
||||
|
||||
nsIContent* kid = GetChildAt(aIndex);
|
||||
if (kid) {
|
||||
return doRemoveChildAt(aIndex, aNotify, kid, mContent, mDocument,
|
||||
aChildArray);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* mContent;
|
||||
nsIDocument* mDocument;
|
||||
};
|
||||
|
||||
|
||||
static nsresult
|
||||
doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
/* static */
|
||||
nsresult
|
||||
nsGenericElement::doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
||||
nsIContent* aKid, nsIContent* aParent,
|
||||
nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
NS_PRECONDITION(!aParent || aParent->GetCurrentDoc() == aDocument,
|
||||
"Incorrect aDocument");
|
||||
|
||||
nsContentOrDocument container(aParent, aDocument);
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
|
||||
NS_PRECONDITION(aKid && aKid->GetParent() == aParent &&
|
||||
aKid == container.GetChildAt(aIndex), "Bogus aKid");
|
||||
aKid == container->GetChildAt(aIndex), "Bogus aKid");
|
||||
|
||||
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
|
@ -2939,21 +2800,11 @@ doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid,
|
|||
// Someone may have removed the kid while that event was processing...
|
||||
if (!hasListeners ||
|
||||
(aKid->GetParent() == aParent &&
|
||||
aKid == container.GetChildAt(aIndex))) {
|
||||
aKid == container->GetChildAt(aIndex))) {
|
||||
if (aParent) {
|
||||
nsRange::OwnerChildRemoved(aParent, aIndex, aKid);
|
||||
}
|
||||
|
||||
// Note that SetRootContent already deals with unbinding, so if we plan to
|
||||
// call it we shouldn't unbind ourselves. It also deals with removing the
|
||||
// node from the child array, but not with notifying, unfortunately. So we
|
||||
// have to call ContentRemoved ourselves after setting the root content.
|
||||
if (!aParent && aKid->IsContentOfType(nsIContent::eELEMENT)) {
|
||||
aDocument->SetRootContent(nsnull);
|
||||
if (aNotify) {
|
||||
aDocument->ContentRemoved(aParent, aKid, aIndex);
|
||||
}
|
||||
} else {
|
||||
aChildArray.RemoveChildAt(aIndex);
|
||||
|
||||
if (aNotify && aDocument) {
|
||||
|
@ -2962,7 +2813,6 @@ doRemoveChildAt(PRUint32 aIndex, PRBool aNotify, nsIContent* aKid,
|
|||
|
||||
aKid->UnbindFromTree();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3014,7 +2864,7 @@ nsGenericElement::InsertBefore(nsIDOMNode *aNewChild, nsIDOMNode *aRefChild,
|
|||
nsIDOMNode **aReturn)
|
||||
{
|
||||
return doInsertBefore(aNewChild, aRefChild, this, GetCurrentDoc(),
|
||||
mAttrsAndChildren, aReturn);
|
||||
aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3022,14 +2872,14 @@ nsGenericElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
nsIDOMNode** aReturn)
|
||||
{
|
||||
return doReplaceChild(aNewChild, aOldChild, this, GetCurrentDoc(),
|
||||
mAttrsAndChildren, aReturn);
|
||||
aReturn);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericElement::RemoveChild(nsIDOMNode *aOldChild, nsIDOMNode **aReturn)
|
||||
{
|
||||
return doRemoveChild(aOldChild, this, GetCurrentDoc(),
|
||||
mAttrsAndChildren, aReturn);
|
||||
aReturn);
|
||||
}
|
||||
|
||||
// When replacing, aRefContent is the content being replaced; when
|
||||
|
@ -3278,7 +3128,6 @@ NS_IMPL_ISUPPORTS1(nsFragmentObserver, nsIDocumentObserver)
|
|||
nsresult
|
||||
nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray,
|
||||
nsIDOMNode** aReturn)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
|
@ -3295,7 +3144,10 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
nsresult res = NS_OK;
|
||||
PRInt32 refPos = 0;
|
||||
|
||||
nsContentOrDocument container(aParent, aDocument);
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
|
||||
if (aRefChild) {
|
||||
refContent = do_QueryInterface(aRefChild, &res);
|
||||
|
@ -3308,13 +3160,13 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
refPos = container.IndexOf(refContent);
|
||||
refPos = container->IndexOf(refContent);
|
||||
|
||||
if (refPos < 0) {
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
} else {
|
||||
refPos = container.GetChildCount();
|
||||
refPos = container->GetChildCount();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> newContent(do_QueryInterface(aNewChild, &res));
|
||||
|
@ -3344,7 +3196,7 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
// what should a caller with UniversalBrowserRead/Write/whatever be able to
|
||||
// do, exactly? Do we need to be more careful with documents because random
|
||||
// callers _can_ get access to them? That might be....
|
||||
if (old_doc && old_doc != container.GetOwnerDoc()) {
|
||||
if (old_doc && old_doc != container->GetOwnerDoc()) {
|
||||
if (aParent) {
|
||||
if (!nsContentUtils::CanCallerAccess(aNewChild)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -3376,7 +3228,7 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
NS_ENSURE_TRUE(doc_fragment, NS_ERROR_UNEXPECTED);
|
||||
|
||||
PRUint32 count = newContent->GetChildCount();
|
||||
PRUint32 old_count = container.GetChildCount();
|
||||
PRUint32 old_count = container->GetChildCount();
|
||||
|
||||
PRBool do_notify = !!aRefChild || !aParent;
|
||||
|
||||
|
@ -3414,8 +3266,7 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
|
||||
// XXXbz how come no reparenting here? That seems odd...
|
||||
// Insert the child and increment the insertion position
|
||||
res = container.InsertChildAt(childContent, refPos++, do_notify,
|
||||
aChildArray);
|
||||
res = container->InsertChildAt(childContent, refPos++, do_notify);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
break;
|
||||
|
@ -3465,14 +3316,14 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
if (oldParent) {
|
||||
nsCOMPtr<nsIDOMNode> tmpNode;
|
||||
|
||||
PRUint32 origChildCount = container.GetChildCount();
|
||||
PRUint32 origChildCount = container->GetChildCount();
|
||||
|
||||
/*
|
||||
* We don't care here if the return fails or not.
|
||||
*/
|
||||
oldParent->RemoveChild(aNewChild, getter_AddRefs(tmpNode));
|
||||
|
||||
PRUint32 newChildCount = container.GetChildCount();
|
||||
PRUint32 newChildCount = container->GetChildCount();
|
||||
|
||||
/*
|
||||
* Check if our child count changed during the RemoveChild call, if
|
||||
|
@ -3487,7 +3338,7 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
* previous siblings.
|
||||
*/
|
||||
|
||||
if (refContent == container.GetChildAt(refPos - 1)) {
|
||||
if (refContent == container->GetChildAt(refPos - 1)) {
|
||||
refPos--;
|
||||
}
|
||||
} else {
|
||||
|
@ -3501,11 +3352,11 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
|
||||
if (!newContent->IsContentOfType(eXUL)) {
|
||||
nsContentUtils::ReparentContentWrapper(newContent, aParent,
|
||||
container.GetOwnerDoc(),
|
||||
container->GetOwnerDoc(),
|
||||
old_doc);
|
||||
}
|
||||
|
||||
res = container.InsertChildAt(newContent, refPos, PR_TRUE, aChildArray);
|
||||
res = container->InsertChildAt(newContent, refPos, PR_TRUE);
|
||||
|
||||
if (NS_FAILED(res)) {
|
||||
return res;
|
||||
|
@ -3522,7 +3373,6 @@ nsGenericElement::doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
|||
nsresult
|
||||
nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray,
|
||||
nsIDOMNode** aReturn)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
|
@ -3540,16 +3390,19 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
|
||||
nsCOMPtr<nsIContent> oldContent = do_QueryInterface(aOldChild);
|
||||
|
||||
nsContentOrDocument container(aParent, aDocument);
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
|
||||
// if oldContent is null IndexOf will return < 0, which is what we want
|
||||
// since aOldChild couldn't be a child.
|
||||
oldPos = container.IndexOf(oldContent);
|
||||
oldPos = container->IndexOf(oldContent);
|
||||
if (oldPos < 0) {
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> replacedChild = container.GetChildAt(oldPos);
|
||||
nsCOMPtr<nsIContent> replacedChild = container->GetChildAt(oldPos);
|
||||
|
||||
PRUint16 nodeType = 0;
|
||||
|
||||
|
@ -3578,7 +3431,7 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
// what should a caller with UniversalBrowserRead/Write/whatever be able to
|
||||
// do, exactly? Do we need to be more careful with documents because random
|
||||
// callers _can_ get access to them? That might be....
|
||||
if (old_doc && old_doc != container.GetOwnerDoc()) {
|
||||
if (old_doc && old_doc != container->GetOwnerDoc()) {
|
||||
if (aParent) {
|
||||
if (!nsContentUtils::CanCallerAccess(aNewChild)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
|
@ -3611,7 +3464,7 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
if (nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
|
||||
nsCOMPtr<nsIContent> childContent;
|
||||
PRUint32 i, count = newContent->GetChildCount();
|
||||
res = container.RemoveChildAt(oldPos, PR_TRUE, aChildArray);
|
||||
res = container->RemoveChildAt(oldPos, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
/*
|
||||
|
@ -3626,12 +3479,9 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
res = newContent->RemoveChildAt(0, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// XXXbz need a way to insert into document here.... Maybe it's time for
|
||||
// nsIContentContainer? ;)
|
||||
// XXXbz how come no reparenting here?
|
||||
// Insert the child and increment the insertion position
|
||||
res = container.InsertChildAt(childContent, oldPos++, PR_TRUE,
|
||||
aChildArray);
|
||||
res = container->InsertChildAt(childContent, oldPos++, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
|
@ -3647,7 +3497,7 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
* new child is alleady a child of this node-- jst@citec.fi
|
||||
*/
|
||||
if (oldParent) {
|
||||
PRUint32 origChildCount = container.GetChildCount();
|
||||
PRUint32 origChildCount = container->GetChildCount();
|
||||
|
||||
/*
|
||||
* We don't care here if the return fails or not.
|
||||
|
@ -3655,7 +3505,7 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
nsCOMPtr<nsIDOMNode> tmpNode;
|
||||
oldParent->RemoveChild(aNewChild, getter_AddRefs(tmpNode));
|
||||
|
||||
PRUint32 newChildCount = container.GetChildCount();
|
||||
PRUint32 newChildCount = container->GetChildCount();
|
||||
|
||||
/*
|
||||
* Check if our child count changed during the RemoveChild call, if
|
||||
|
@ -3667,7 +3517,7 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
* Check if aOldChild is now at oldPos - 1, this will happend if
|
||||
* the new child was one of aOldChilds' previous siblings.
|
||||
*/
|
||||
nsIContent *tmpContent = container.GetChildAt(oldPos - 1);
|
||||
nsIContent *tmpContent = container->GetChildAt(oldPos - 1);
|
||||
|
||||
if (oldContent == tmpContent) {
|
||||
oldPos--;
|
||||
|
@ -3677,18 +3527,18 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
|
||||
if (!newContent->IsContentOfType(eXUL)) {
|
||||
nsContentUtils::ReparentContentWrapper(newContent, aParent,
|
||||
container.GetOwnerDoc(),
|
||||
container->GetOwnerDoc(),
|
||||
old_doc);
|
||||
}
|
||||
|
||||
// If we're replacing a child with itself the child
|
||||
// has already been removed from this element once we get here.
|
||||
if (aNewChild != aOldChild) {
|
||||
res = container.RemoveChildAt(oldPos, PR_TRUE, aChildArray);
|
||||
res = container->RemoveChildAt(oldPos, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
|
||||
res = container.InsertChildAt(newContent, oldPos, PR_TRUE, aChildArray);
|
||||
res = container->InsertChildAt(newContent, oldPos, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
|
||||
|
@ -3699,7 +3549,6 @@ nsGenericElement::doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
|||
nsresult
|
||||
nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray,
|
||||
nsIDOMNode** aReturn)
|
||||
{
|
||||
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
||||
|
@ -3709,16 +3558,20 @@ nsGenericElement::doRemoveChild(nsIDOMNode* aOldChild,
|
|||
*aReturn = nsnull;
|
||||
NS_ENSURE_TRUE(aOldChild, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsINode* container = aParent;
|
||||
if (!container) {
|
||||
container = aDocument;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aOldChild);
|
||||
// fix children to be a passed argument
|
||||
PRInt32 index = aChildArray.IndexOfChild(content);
|
||||
PRInt32 index = container->IndexOf(content);
|
||||
if (index == -1) {
|
||||
// aOldChild isn't one of our children.
|
||||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
nsContentOrDocument container(aParent, aDocument);
|
||||
nsresult rv = container.RemoveChildAt(index, PR_TRUE, aChildArray);
|
||||
nsresult rv = container->RemoveChildAt(index, PR_TRUE);
|
||||
|
||||
*aReturn = aOldChild;
|
||||
NS_ADDREF(aOldChild);
|
||||
|
@ -3742,6 +3595,7 @@ NS_INTERFACE_MAP_BEGIN(nsGenericElement)
|
|||
nsDOMEventRTTearoff::Create(this))
|
||||
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNSEventTarget,
|
||||
nsDOMEventRTTearoff::Create(this))
|
||||
NS_INTERFACE_MAP_ENTRY(nsINode)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
|
|
@ -356,6 +356,15 @@ public:
|
|||
virtual nsIDOMGCParticipant* GetSCCIndex();
|
||||
virtual void AppendReachableList(nsCOMArray<nsIDOMGCParticipant>& aArray);
|
||||
|
||||
// nsINode interface methods
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
|
||||
// nsIContent interface methods
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
|
@ -364,13 +373,6 @@ public:
|
|||
PRBool aNullParent = PR_TRUE);
|
||||
virtual PRBool IsNativeAnonymous() const;
|
||||
virtual void SetNativeAnonymous(PRBool aAnonymous);
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify);
|
||||
virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetClassAttributeName() const;
|
||||
virtual already_AddRefed<nsINodeInfo> GetExistingAttrNameFromQName(const nsAString& aStr) const;
|
||||
|
@ -640,12 +642,10 @@ public:
|
|||
* @param aDocument The document to use for the new child.
|
||||
* Must be non-null, if aParent is null and must match
|
||||
* aParent->GetCurrentDoc() if aParent is not null.
|
||||
* @param aChildArray The child array to work with
|
||||
* @param aReturn [out] the child we insert
|
||||
*/
|
||||
static nsresult doInsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray,
|
||||
nsIDOMNode** aReturn);
|
||||
|
||||
/**
|
||||
|
@ -663,7 +663,6 @@ public:
|
|||
*/
|
||||
static nsresult doReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray,
|
||||
nsIDOMNode** aReturn);
|
||||
|
||||
/**
|
||||
|
@ -675,14 +674,50 @@ public:
|
|||
* @param aDocument The document to use for the new child.
|
||||
* Must be non-null if aParent is null and must match
|
||||
* aParent->GetCurrentDoc() if aParent is not null.
|
||||
* @param aChildArray The child array to work with
|
||||
* @param aReturn [out] the child we remove
|
||||
*/
|
||||
static nsresult doRemoveChild(nsIDOMNode* aOldChild,
|
||||
nsIContent* aParent, nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray,
|
||||
nsIDOMNode** aReturn);
|
||||
|
||||
/**
|
||||
* Most of the implementation of the nsINode InsertChildAt method. Shared by
|
||||
* nsDocument. When called from nsDocument, aParent will be null.
|
||||
*
|
||||
* @param aKid The child to insert.
|
||||
* @param aIndex The index to insert at.
|
||||
* @param aNotify Whether to notify.
|
||||
* @param aParent The parent to use for the new child.
|
||||
* @param aDocument The document to use for the notifications. Must be
|
||||
* non-null if aParent is null (in which case aKid is being
|
||||
* inserted as its child) and must match
|
||||
* aParent->GetCurrentDoc() if aParent is not null.
|
||||
* @param aChildArray The child array to work with
|
||||
*/
|
||||
static nsresult doInsertChildAt(nsIContent* aKid, PRUint32 aIndex,
|
||||
PRBool aNotify, nsIContent* aParent,
|
||||
nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray);
|
||||
|
||||
/**
|
||||
* Most of the implementation of the nsINode RemoveChildAt method. Shared by
|
||||
* nsDocument. When called from nsDocument, aParent will be null.
|
||||
*
|
||||
* @param aIndex The index to remove at.
|
||||
* @param aNotify Whether to notify.
|
||||
* @param aKid The kid at aIndex. Must not be null.
|
||||
* @param aParent The parent we're removing from.
|
||||
* @param aDocument The document to use for the notifications. Must be
|
||||
* non-null if aParent is null (in which case aKid is being
|
||||
* removed as its child) and must match
|
||||
* aParent->GetCurrentDoc() if aParent is not null.
|
||||
* @param aChildArray The child array to work with
|
||||
*/
|
||||
static nsresult doRemoveChildAt(PRUint32 aIndex, PRBool aNotify,
|
||||
nsIContent* aKid, nsIContent* aParent,
|
||||
nsIDocument* aDocument,
|
||||
nsAttrAndChildArray& aChildArray);
|
||||
|
||||
static nsresult InitHashes();
|
||||
|
||||
static PLDHashTable sEventListenerManagersHash;
|
||||
|
|
|
@ -1192,6 +1192,7 @@ GK_ATOM(secondsFromDateTime, "seconds-from-dateTime")
|
|||
// Node types
|
||||
GK_ATOM(cdataTagName, "#cdata-section")
|
||||
GK_ATOM(commentTagName, "#comment")
|
||||
GK_ATOM(documentNodeName, "#document")
|
||||
GK_ATOM(documentFragmentNodeName, "#document-fragment")
|
||||
GK_ATOM(documentTypeNodeName, "#document-type")
|
||||
GK_ATOM(processingInstructionTagName, "#processing-instruction")
|
||||
|
|
|
@ -82,7 +82,8 @@ nsNodeInfoManager::NodeInfoInnerKeyCompare(const void *key1, const void *key2)
|
|||
nsNodeInfoManager::nsNodeInfoManager()
|
||||
: mDocument(nsnull),
|
||||
mTextNodeInfo(nsnull),
|
||||
mCommentNodeInfo(nsnull)
|
||||
mCommentNodeInfo(nsnull),
|
||||
mDocumentNodeInfo(nsnull)
|
||||
{
|
||||
++gNodeManagerCount;
|
||||
|
||||
|
@ -289,6 +290,19 @@ nsNodeInfoManager::GetCommentNodeInfo()
|
|||
return mCommentNodeInfo;
|
||||
}
|
||||
|
||||
already_AddRefed<nsINodeInfo>
|
||||
nsNodeInfoManager::GetDocumentNodeInfo()
|
||||
{
|
||||
if (!mDocumentNodeInfo) {
|
||||
GetNodeInfo(nsLayoutAtoms::documentNodeName, nsnull, kNameSpaceID_None,
|
||||
&mDocumentNodeInfo);
|
||||
}
|
||||
else {
|
||||
NS_ADDREF(mDocumentNodeInfo);
|
||||
}
|
||||
|
||||
return mDocumentNodeInfo;
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
nsNodeInfoManager::GetDocumentPrincipal()
|
||||
|
@ -331,6 +345,9 @@ nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
|
|||
else if (aNodeInfo == mCommentNodeInfo) {
|
||||
mCommentNodeInfo = nsnull;
|
||||
}
|
||||
else if (aNodeInfo == mDocumentNodeInfo) {
|
||||
mDocumentNodeInfo = nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool ret =
|
||||
|
|
|
@ -84,8 +84,17 @@ public:
|
|||
* Returns the nodeinfo for text nodes. Can return null if OOM.
|
||||
*/
|
||||
already_AddRefed<nsINodeInfo> GetTextNodeInfo();
|
||||
|
||||
/**
|
||||
* Returns the nodeinfo for comment nodes. Can return null if OOM.
|
||||
*/
|
||||
already_AddRefed<nsINodeInfo> GetCommentNodeInfo();
|
||||
|
||||
/**
|
||||
* Returns the nodeinfo for the document node. Can return null if OOM.
|
||||
*/
|
||||
already_AddRefed<nsINodeInfo> GetDocumentNodeInfo();
|
||||
|
||||
/**
|
||||
* Retrieve a pointer to the document that owns this node info
|
||||
* manager.
|
||||
|
@ -121,6 +130,7 @@ private:
|
|||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsINodeInfo *mTextNodeInfo; // WEAK to avoid circular ownership
|
||||
nsINodeInfo *mCommentNodeInfo; // WEAK to avoid circular ownership
|
||||
nsINodeInfo *mDocumentNodeInfo; // WEAK to avoid circular ownership
|
||||
|
||||
static PRUint32 gNodeManagerCount;
|
||||
};
|
||||
|
|
|
@ -2113,7 +2113,9 @@ HTMLContentSink::Init(nsIDocument* aDoc,
|
|||
}
|
||||
NS_ADDREF(mRoot);
|
||||
|
||||
rv = mDocument->SetRootContent(mRoot);
|
||||
NS_ASSERTION(mDocument->GetChildCount() == 0,
|
||||
"Document should have no kids here!");
|
||||
rv = mDocument->AppendChildTo(mRoot, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -3051,12 +3053,6 @@ HTMLContentSink::AddDocTypeDecl(const nsIParserNode& aNode)
|
|||
MOZ_TIMER_DEBUGLOG(("Start: nsHTMLContentSink::AddDocTypeDecl()\n"));
|
||||
MOZ_TIMER_START(mWatch);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(mHTMLDocument));
|
||||
|
||||
if (!doc) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString docTypeStr(aNode.GetText());
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -3239,6 +3235,7 @@ HTMLContentSink::AddDocTypeDecl(const nsIParserNode& aNode)
|
|||
nsCOMPtr<nsIDOMDocumentType> oldDocType;
|
||||
nsCOMPtr<nsIDOMDocumentType> docType;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(mHTMLDocument));
|
||||
doc->GetDoctype(getter_AddRefs(oldDocType));
|
||||
|
||||
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
|
||||
|
@ -3259,25 +3256,19 @@ HTMLContentSink::AddDocTypeDecl(const nsIParserNode& aNode)
|
|||
if (NS_FAILED(rv) || !docType) {
|
||||
return rv;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> tmpNode;
|
||||
|
||||
if (oldDocType) {
|
||||
// If we already have a doctype we replace the old one.
|
||||
|
||||
nsCOMPtr<nsIDOMNode> tmpNode;
|
||||
rv = doc->ReplaceChild(oldDocType, docType, getter_AddRefs(tmpNode));
|
||||
} else {
|
||||
// If we don't already have one we insert it as the first child,
|
||||
// this might not be 100% correct but since this is called from
|
||||
// the content sink we assume that this is what we want.
|
||||
nsCOMPtr<nsIDOMNode> firstChild;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(docType);
|
||||
NS_ASSERTION(content, "Doctype isn't content?");
|
||||
|
||||
doc->GetFirstChild(getter_AddRefs(firstChild));
|
||||
|
||||
// If the above fails it must be because we don't have any child
|
||||
// nodes, then firstChild will be 0 and InsertBefore() will
|
||||
// append
|
||||
|
||||
rv = doc->InsertBefore(docType, firstChild, getter_AddRefs(tmpNode));
|
||||
mDocument->InsertChildAt(content, 0, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -243,7 +243,8 @@ nsMediaDocument::CreateSyntheticDocument()
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
rv = SetRootContent(root);
|
||||
NS_ASSERTION(GetChildCount() == 0, "Shouldn't have any kids");
|
||||
rv = AppendChildTo(root, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mNodeInfoManager->GetNodeInfo(nsHTMLAtoms::body, nsnull,
|
||||
|
|
|
@ -564,11 +564,8 @@ nsXMLContentSink::AddContentAsLeaf(nsIContent *aContent)
|
|||
|
||||
if ((eXMLContentSinkState_InProlog == mState) ||
|
||||
(eXMLContentSinkState_InEpilog == mState)) {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc( do_QueryInterface(mDocument) );
|
||||
nsCOMPtr<nsIDOMNode> trash;
|
||||
nsCOMPtr<nsIDOMNode> child( do_QueryInterface(aContent) );
|
||||
NS_ASSERTION(child, "not a dom node");
|
||||
domDoc->AppendChild(child, getter_AddRefs(trash));
|
||||
NS_ASSERTION(mDocument, "Fragments have no prolog or epilog");
|
||||
mDocument->AppendChildTo(aContent, PR_FALSE);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIContent> parent = GetCurrentContent();
|
||||
|
@ -869,7 +866,7 @@ nsXMLContentSink::SetDocElement(PRInt32 aNameSpaceID,
|
|||
mDocElement = aContent;
|
||||
NS_ADDREF(mDocElement);
|
||||
|
||||
nsresult rv = mDocument->SetRootContent(mDocElement);
|
||||
nsresult rv = mDocument->AppendChildTo(mDocElement, PR_FALSE);
|
||||
if (NS_FAILED(rv)) {
|
||||
// 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.
|
||||
|
@ -1077,9 +1074,7 @@ nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset,
|
|||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc(do_QueryInterface(mDocument));
|
||||
if (!doc)
|
||||
return NS_OK;
|
||||
NS_ASSERTION(mDocument, "Shouldn't get here from a document fragment");
|
||||
|
||||
nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
|
||||
NS_ENSURE_TRUE(name, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
@ -1114,9 +1109,10 @@ nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset,
|
|||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> tmpNode;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(docType);
|
||||
NS_ASSERTION(content, "doctype isn't content?");
|
||||
|
||||
return doc->AppendChild(docType, getter_AddRefs(tmpNode));
|
||||
return mDocument->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -253,16 +253,14 @@ void txMozillaTextOutput::createResultDocument(nsIDOMDocument* aSourceDocument,
|
|||
mDocument->CreateElementNS(XHTML_NSURI,
|
||||
NS_LITERAL_STRING("html"),
|
||||
getter_AddRefs(docElement));
|
||||
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(docElement);
|
||||
NS_ASSERTION(rootContent, "Need root element");
|
||||
if (!rootContent) {
|
||||
if (!docElement) {
|
||||
// Out of memory
|
||||
NS_WARNING("Failed to create documentElement");
|
||||
return;
|
||||
}
|
||||
|
||||
// XXXbz what to do on failure here?
|
||||
rv = doc->SetRootContent(rootContent);
|
||||
rv = mDocument->AppendChild(docElement, getter_AddRefs(parent));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to set root content");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,8 @@ txMozillaXMLOutput::txMozillaXMLOutput(const nsAString& aRootName,
|
|||
mDontAddCurrent(PR_FALSE),
|
||||
mHaveTitleElement(PR_FALSE),
|
||||
mHaveBaseElement(PR_FALSE),
|
||||
mCreatingNewDocument(PR_TRUE)
|
||||
mCreatingNewDocument(PR_TRUE),
|
||||
mRootContentCreated(PR_FALSE)
|
||||
{
|
||||
if (aObserver) {
|
||||
mNotifier = new txTransformNotifier();
|
||||
|
@ -304,16 +305,15 @@ void txMozillaXMLOutput::endElement(const nsAString& aName, const PRInt32 aNsID)
|
|||
// BindToTree manually
|
||||
if (mCurrentNode == mNonAddedNode) {
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(mNonAddedParent);
|
||||
if (document && !mRootContent) {
|
||||
mRootContent = do_QueryInterface(mCurrentNode);
|
||||
// XXXbz what to do on failure here?
|
||||
document->SetRootContent(mRootContent);
|
||||
NS_ASSERTION(!document || !mRootContentCreated,
|
||||
"mNonAddedParent shouldn't be a document if we have a "
|
||||
"root content");
|
||||
if (document) {
|
||||
mRootContentCreated = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
mNonAddedParent->AppendChild(mCurrentNode,
|
||||
getter_AddRefs(resultNode));
|
||||
}
|
||||
mNonAddedParent->AppendChild(mCurrentNode, getter_AddRefs(resultNode));
|
||||
mCurrentNode = mNonAddedParent;
|
||||
mNonAddedParent = nsnull;
|
||||
mNonAddedNode = nsnull;
|
||||
|
@ -477,7 +477,7 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
|
|||
nsCOMPtr<nsIDocument> document = do_QueryInterface(mParentNode);
|
||||
nsCOMPtr<nsIDOMElement> currentElement = do_QueryInterface(mCurrentNode);
|
||||
|
||||
if (document && currentElement && mRootContent) {
|
||||
if (document && currentElement && mRootContentCreated) {
|
||||
// We already have a document element, but the XSLT spec allows this.
|
||||
// As a workaround, create a wrapper object and use that as the
|
||||
// document element.
|
||||
|
@ -491,14 +491,11 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
|
|||
mNonAddedNode = mCurrentNode;
|
||||
}
|
||||
else {
|
||||
if (document && currentElement && !mRootContent) {
|
||||
mRootContent = do_QueryInterface(mCurrentNode);
|
||||
// XXXbz what to do on failure here?
|
||||
document->SetRootContent(mRootContent);
|
||||
if (document && currentElement) {
|
||||
mRootContentCreated = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
rv = mParentNode->AppendChild(mCurrentNode, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(rv)) {
|
||||
mBadChildLevel = 1;
|
||||
|
@ -515,7 +512,6 @@ void txMozillaXMLOutput::closePrevious(PRInt8 aAction)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mParentNode = nsnull;
|
||||
}
|
||||
else if ((aAction & eFlushText) && !mText.IsEmpty()) {
|
||||
|
@ -559,16 +555,22 @@ txMozillaXMLOutput::createTxWrapper()
|
|||
|
||||
nsCOMPtr<nsIDOMNode> child, resultNode;
|
||||
PRUint32 i, j, childCount = document->GetChildCount();
|
||||
#ifdef DEBUG
|
||||
// Keep track of the location of the current documentElement, if there is
|
||||
// one, so we can verify later
|
||||
PRUint32 rootLocation = 0;
|
||||
#endif
|
||||
for (i = 0, j = 0; i < childCount; ++i) {
|
||||
nsIContent* childContent = document->GetChildAt(j);
|
||||
child = do_QueryInterface(childContent);
|
||||
if (childContent == mRootContent) {
|
||||
document->SetRootContent(nsnull);
|
||||
}
|
||||
PRUint16 nodeType;
|
||||
child->GetNodeType(&nodeType);
|
||||
switch (nodeType) {
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
#ifdef DEBUG
|
||||
rootLocation = j;
|
||||
// Fall through
|
||||
#endif
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
case nsIDOMNode::CDATA_SECTION_NODE:
|
||||
case nsIDOMNode::ENTITY_REFERENCE_NODE:
|
||||
|
@ -582,7 +584,16 @@ txMozillaXMLOutput::createTxWrapper()
|
|||
// Failed to remove the content, skip it in next iteration
|
||||
++j;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case nsIDOMNode::DOCUMENT_TYPE_NODE:
|
||||
#ifdef DEBUG
|
||||
// The new documentElement should go after the document type.
|
||||
// This is needed for cases when there is no existing
|
||||
// documentElement in the document.
|
||||
rootLocation = PR_MAX(rootLocation, j+1);
|
||||
// Fall through
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
++j;
|
||||
|
@ -597,8 +608,12 @@ txMozillaXMLOutput::createTxWrapper()
|
|||
mCurrentNode = wrapper;
|
||||
}
|
||||
|
||||
mRootContent = do_QueryInterface(wrapper);
|
||||
return document->SetRootContent(mRootContent);
|
||||
mRootContentCreated = PR_TRUE;
|
||||
nsCOMPtr<nsIContent> wrapperContent = do_QueryInterface(wrapper);
|
||||
NS_ASSERTION(wrapperContent, "Must have wrapper content");
|
||||
NS_ASSERTION(rootLocation = document->GetChildCount(),
|
||||
"Incorrect root location");
|
||||
return document->AppendChildTo(wrapperContent, PR_TRUE);
|
||||
}
|
||||
|
||||
void txMozillaXMLOutput::startHTMLElement(nsIDOMElement* aElement, PRBool aXHTML)
|
||||
|
|
|
@ -119,7 +119,6 @@ private:
|
|||
nsCOMPtr<nsIDOMDocument> mDocument;
|
||||
nsCOMPtr<nsIDOMNode> mCurrentNode;
|
||||
nsCOMPtr<nsIDOMNode> mParentNode;
|
||||
nsCOMPtr<nsIContent> mRootContent;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> mNonAddedParent;
|
||||
nsCOMPtr<nsIDOMNode> mNonAddedNode;
|
||||
|
@ -149,6 +148,9 @@ private:
|
|||
PRPackedBool mDocumentIsHTML;
|
||||
PRPackedBool mCreatingNewDocument;
|
||||
|
||||
// Set to true when we know there's a root content in our document.
|
||||
PRPackedBool mRootContentCreated;
|
||||
|
||||
enum txAction { eCloseElement = 1, eFlushText = 2 };
|
||||
};
|
||||
|
||||
|
|
|
@ -907,12 +907,8 @@ txMozillaXSLTProcessor::notifyError()
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> rootContent = do_QueryInterface(element);
|
||||
if (!rootContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = document->SetRootContent(rootContent);
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
rv = errorDocument->AppendChild(element, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -923,7 +919,6 @@ txMozillaXSLTProcessor::notifyError()
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
rv = element->AppendChild(text, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
|
|
|
@ -463,6 +463,11 @@ public:
|
|||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsINode
|
||||
virtual PRUint32 GetChildCount() const;
|
||||
virtual nsIContent *GetChildAt(PRUint32 aIndex) const;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
|
||||
// nsIContent
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
|
@ -470,9 +475,6 @@ public:
|
|||
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;
|
||||
virtual PRInt32 IndexOf(nsIContent* aPossibleChild) const;
|
||||
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
|
||||
virtual nsIAtom *GetIDAttributeName() const;
|
||||
virtual nsIAtom *GetClassAttributeName() const;
|
||||
|
|
|
@ -2449,7 +2449,7 @@ nsXULDocument::PrepareToWalk()
|
|||
rv = CreateElementFromPrototype(proto, getter_AddRefs(root));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = SetRootContent(root);
|
||||
rv = AppendChildTo(root, PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Add the root element to the XUL document's ID-to-element map.
|
||||
|
|
|
@ -56,6 +56,7 @@ REQUIRES = xpcom \
|
|||
necko \
|
||||
widget \
|
||||
content \
|
||||
dom \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
|
|
|
@ -38,12 +38,12 @@
|
|||
#define nsDetectionAdaptor_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIWebShellServices.h"
|
||||
|
||||
#include "nsIParserFilter.h"
|
||||
static NS_DEFINE_IID(kIParserFilterIID, NS_IPARSERFILTER_IID);
|
||||
|
||||
class nsIDocument;
|
||||
class CToken;
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
|
|
@ -366,7 +366,9 @@ nsContentDLF::CreateBlankDocument(nsILoadGroup *aLoadGroup, nsIDocument **aDocum
|
|||
|
||||
// blat in the structure
|
||||
if (htmlElement && headElement && bodyElement) {
|
||||
rv = blankDoc->SetRootContent(htmlElement);
|
||||
NS_ASSERTION(blankDoc->GetChildCount() == 0,
|
||||
"Shouldn't have children");
|
||||
rv = blankDoc->AppendChildTo(htmlElement, PR_FALSE);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = htmlElement->AppendChildTo(headElement, PR_FALSE);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче