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:
bzbarsky%mit.edu 2006-01-19 03:34:18 +00:00
Родитель 7105c7c96d
Коммит b64fcb4a39
27 изменённых файлов: 595 добавлений и 489 удалений

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

@ -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,19 +104,22 @@ 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.
* @param aCommand The parser command
@ -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,37 +2672,33 @@ nsGenericElement::InsertChildAt(nsIContent* aKid,
}
static nsresult
doInsertChildAt(nsIContent* aKid, PRUint32 aIndex, PRBool aNotify,
nsIContent* aParent, nsIDocument* aDocument,
nsAttrAndChildArray& aChildArray)
/* 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");
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);
PRBool isAppend = (aIndex == aChildArray.ChildCount());
rv = aKid->BindToTree(aDocument, aParent, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
aChildArray.RemoveChildAt(aIndex);
aKid->UnbindFromTree();
return rv;
}
mozAutoDocUpdate updateBatch(aDocument, UPDATE_CONTENT_MODEL, aNotify);
nsresult rv = aChildArray.InsertChildAt(aKid, aIndex);
NS_ENSURE_SUCCESS(rv, rv);
rv = aKid->BindToTree(aDocument, aParent, nsnull, PR_TRUE);
if (NS_FAILED(rv)) {
aChildArray.RemoveChildAt(aIndex);
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,
nsAttrAndChildArray& aChildArray)
/* 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,29 +2800,18 @@ 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);
aChildArray.RemoveChildAt(aIndex);
if (aNotify && aDocument) {
aDocument->ContentRemoved(aParent, aKid, aIndex);
}
aKid->UnbindFromTree();
if (aNotify && aDocument) {
aDocument->ContentRemoved(aParent, aKid, aIndex);
}
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;
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));
nsCOMPtr<nsIContent> content = do_QueryInterface(docType);
NS_ASSERTION(content, "Doctype isn't content?");
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;
return doc->AppendChild(docType, getter_AddRefs(tmpNode));
nsCOMPtr<nsIContent> content = do_QueryInterface(docType);
NS_ASSERTION(content, "doctype isn't content?");
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);
}
else {
nsCOMPtr<nsIDOMNode> resultNode;
mNonAddedParent->AppendChild(mCurrentNode,
getter_AddRefs(resultNode));
NS_ASSERTION(!document || !mRootContentCreated,
"mNonAddedParent shouldn't be a document if we have a "
"root content");
if (document) {
mRootContentCreated = PR_TRUE;
}
nsCOMPtr<nsIDOMNode> 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,28 +491,24 @@ 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;
rv = mParentNode->AppendChild(mCurrentNode, getter_AddRefs(resultNode));
if (NS_FAILED(rv)) {
mBadChildLevel = 1;
mCurrentNode = mParentNode;
PR_LOG(txLog::xslt, PR_LOG_DEBUG,
("closePrevious, mBadChildLevel = %d\n",
mBadChildLevel));
// warning to the console
nsCOMPtr<nsIConsoleService> consoleSvc =
do_GetService("@mozilla.org/consoleservice;1", &rv);
if (consoleSvc) {
consoleSvc->LogStringMessage(
NS_LITERAL_STRING("failed to create XSLT content").get());
}
nsCOMPtr<nsIDOMNode> resultNode;
rv = mParentNode->AppendChild(mCurrentNode, getter_AddRefs(resultNode));
if (NS_FAILED(rv)) {
mBadChildLevel = 1;
mCurrentNode = mParentNode;
PR_LOG(txLog::xslt, PR_LOG_DEBUG,
("closePrevious, mBadChildLevel = %d\n",
mBadChildLevel));
// warning to the console
nsCOMPtr<nsIConsoleService> consoleSvc =
do_GetService("@mozilla.org/consoleservice;1", &rv);
if (consoleSvc) {
consoleSvc->LogStringMessage(
NS_LITERAL_STRING("failed to create XSLT content").get());
}
}
}
@ -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);