Fix for bug 251025 (document.importNode does not set the right owner document.). r=jst, sr=bz.

This commit is contained in:
peterv%propagandism.org 2005-09-11 17:15:08 +00:00
Родитель efa08d1916
Коммит 85b8cff6bc
29 изменённых файлов: 536 добавлений и 401 удалений

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

@ -40,6 +40,7 @@
#ifndef nsIAttribute_h___
#define nsIAttribute_h___
#include "nsIContent.h"
#include "nsISupports.h"
#include "nsINodeInfo.h"
#include "nsIContent.h"
@ -93,6 +94,13 @@ public:
virtual void* UnsetProperty(nsIAtom *aPropertyName,
nsresult *aStatus = nsnull) = 0;
nsIDocument *GetOwnerDoc()
{
nsIContent *content = GetContent();
return content ? content->GetOwnerDoc() : mNodeInfo->GetDocument();
}
protected:
nsIAttribute(nsDOMAttributeMap *aAttrMap, nsINodeInfo *aNodeInfo)
: mAttrMap(aAttrMap), mNodeInfo(aNodeInfo)

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

@ -686,6 +686,23 @@ public:
{ if (aStatus) *aStatus = NS_ERROR_NOT_IMPLEMENTED; return nsnull; }
/**
* Clones this node, setting aOwnerDocument as the ownerDocument of the
* clone. When cloning an element, all attributes of the element will be
* cloned. If aDeep is set, all descendants will also be cloned (by calling
* the DOM method cloneNode on them if aOwnerDocument is the same as the
* ownerDocument of this content node or by calling the DOM method importNode
* if they differ).
*
* @param aOwnerDocument the document to use as the ownerDocument of the
* clone, it should not be null unless this element's
* ownerDocument is null and you don't want to set a
* different ownerDocument.
* @param aDeep whether to clone the descendants of this node
*/
virtual nsresult CloneContent(nsIDocument *aOwnerDocument,
PRBool aDeep, nsIContent **aResult) = 0;
#ifdef DEBUG
/**
* List the content (and anything it contains) out to the given

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

@ -74,9 +74,6 @@ public:
return;
}
#endif
virtual already_AddRefed<nsITextContent> CloneContent(PRBool aCloneText,
nsIDocument *aOwnerDocument);
};
nsresult
@ -161,28 +158,14 @@ nsCommentNode::GetNodeType(PRUint16* aNodeType)
return NS_OK;
}
NS_IMETHODIMP
nsCommentNode::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsGenericDOMDataNode*
nsCommentNode::Clone(nsIDocument *aOwnerDocument, PRBool aCloneText)
{
nsCOMPtr<nsITextContent> textContent = CloneContent(PR_TRUE, GetOwnerDoc());
NS_ENSURE_TRUE(textContent, NS_ERROR_OUT_OF_MEMORY);
return CallQueryInterface(textContent, aReturn);
}
already_AddRefed<nsITextContent>
nsCommentNode::CloneContent(PRBool aCloneText, nsIDocument *aOwnerDocument)
{
nsCommentNode* it = new nsCommentNode(nsnull);
if (!it)
return nsnull;
if (aCloneText) {
nsCommentNode *it = new nsCommentNode(aOwnerDocument);
if (it && aCloneText) {
it->mText = mText;
}
NS_ADDREF(it);
return it;
}

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

@ -365,22 +365,9 @@ nsDOMAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{
*aOwnerDocument = nsnull;
nsresult rv = NS_OK;
nsIContent* content = GetContentInternal();
if (content) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(content, &rv);
if (NS_SUCCEEDED(rv)) {
rv = node->GetOwnerDocument(aOwnerDocument);
}
}
else {
nsIDocument *document = mNodeInfo->GetDocument();
if (document) {
rv = CallQueryInterface(document, aOwnerDocument);
}
}
nsIDocument *document = GetOwnerDoc();
return rv;
return document ? CallQueryInterface(document, aOwnerDocument) : NS_OK;
}
NS_IMETHODIMP

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

@ -192,18 +192,10 @@ nsDOMDocumentType::GetNodeType(PRUint16* aNodeType)
return NS_OK;
}
NS_IMETHODIMP
nsDOMDocumentType::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsGenericDOMDataNode*
nsDOMDocumentType::Clone(nsIDocument *aOwnerDocument, PRBool aCloneText)
{
nsDOMDocumentType* it = new nsDOMDocumentType(mName,
mEntities,
mNotations,
mPublicId,
mSystemId,
mInternalSubset);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
return CallQueryInterface(it, aReturn);
// XXX ownerDocument
return new nsDOMDocumentType(mName, mEntities, mNotations, mPublicId,
mSystemId, mInternalSubset);
}

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

@ -2831,17 +2831,83 @@ nsDocument::GetCharacterSet(nsAString& aCharacterSet)
NS_IMETHODIMP
nsDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
nsIDOMNode** aResult)
{
NS_ENSURE_ARG(aImportedNode);
NS_PRECONDITION(aReturn, "Null out param!");
*aResult = nsnull;
nsresult rv = nsContentUtils::CheckSameOrigin(this, aImportedNode);
if (NS_FAILED(rv)) {
return rv;
}
return aImportedNode->CloneNode(aDeep, aReturn);
PRUint16 nodeType;
aImportedNode->GetNodeType(&nodeType);
switch (nodeType) {
case nsIDOMNode::ATTRIBUTE_NODE:
{
nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aImportedNode);
NS_ENSURE_TRUE(attr, NS_ERROR_FAILURE);
nsIDocument *document = attr->GetOwnerDoc();
nsCOMPtr<nsIDOMAttr> domAttr = do_QueryInterface(aImportedNode);
nsAutoString value;
rv = domAttr->GetValue(value);
NS_ENSURE_SUCCESS(rv, rv);
nsINodeInfo *nodeInfo = attr->NodeInfo();
nsCOMPtr<nsINodeInfo> newNodeInfo;
if (document != this) {
rv = mNodeInfoManager->GetNodeInfo(nodeInfo->NameAtom(),
nodeInfo->GetPrefixAtom(),
nodeInfo->NamespaceID(),
getter_AddRefs(newNodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nodeInfo = newNodeInfo;
}
nsCOMPtr<nsIDOMNode> clone = new nsDOMAttribute(nsnull, nodeInfo,
value);
if (!clone) {
return NS_ERROR_OUT_OF_MEMORY;
}
clone.swap(*aResult);
return NS_OK;
}
case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
case nsIDOMNode::ELEMENT_NODE:
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
case nsIDOMNode::TEXT_NODE:
case nsIDOMNode::CDATA_SECTION_NODE:
case nsIDOMNode::COMMENT_NODE:
{
nsCOMPtr<nsIContent> imported = do_QueryInterface(aImportedNode);
NS_ENSURE_TRUE(imported, NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> clone;
rv = imported->CloneContent(this, aDeep, getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(clone, aResult);
}
case nsIDOMNode::ENTITY_NODE:
case nsIDOMNode::ENTITY_REFERENCE_NODE:
case nsIDOMNode::NOTATION_NODE:
{
return NS_ERROR_NOT_IMPLEMENTED;
}
default:
{
NS_WARNING("Don't know how to clone this nodetype for importNode.");
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
}
}
}
NS_IMETHODIMP

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

@ -55,7 +55,7 @@ class nsDocumentFragment : public nsGenericElement,
public nsIDOM3Node
{
public:
nsDocumentFragment(nsINodeInfo *aNodeInfo, nsIDocument* aOwnerDocument);
nsDocumentFragment(nsINodeInfo *aNodeInfo);
virtual ~nsDocumentFragment();
// nsISupports
@ -91,7 +91,8 @@ public:
*aAttributes = nsnull;
return NS_OK;
}
NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument);
NS_IMETHOD GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{ return nsGenericElement::GetOwnerDocument(aOwnerDocument); }
NS_IMETHOD InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild,
nsIDOMNode** aReturn)
{ return nsGenericElement::InsertBefore(aNewChild, aRefChild, aReturn); }
@ -165,7 +166,8 @@ public:
}
protected:
nsCOMPtr<nsIDocument> mOwnerDocument;
nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult);
};
nsresult
@ -182,23 +184,19 @@ NS_NewDocumentFragment(nsIDOMDocumentFragment** aInstancePtrResult,
getter_AddRefs(nodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
nsDocumentFragment* it = new nsDocumentFragment(nodeInfo, aOwnerDocument);
nsDocumentFragment* it = new nsDocumentFragment(nodeInfo);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aInstancePtrResult = NS_STATIC_CAST(nsIDOMDocumentFragment *, it);
NS_ADDREF(*aInstancePtrResult);
NS_ADDREF(*aInstancePtrResult = it);
return NS_OK;
}
nsDocumentFragment::nsDocumentFragment(nsINodeInfo *aNodeInfo,
nsIDocument* aOwnerDocument)
nsDocumentFragment::nsDocumentFragment(nsINodeInfo *aNodeInfo)
: nsGenericElement(aNodeInfo)
{
mOwnerDocument = aOwnerDocument;
}
nsDocumentFragment::~nsDocumentFragment()
@ -293,64 +291,13 @@ nsDocumentFragment::GetNodeType(PRUint16* aNodeType)
return NS_OK;
}
NS_IMETHODIMP
nsDocumentFragment::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
{
NS_ENSURE_ARG_POINTER(aOwnerDocument);
if (!mOwnerDocument) {
*aOwnerDocument = nsnull;
return NS_OK;
}
return CallQueryInterface(mOwnerDocument, aOwnerDocument);
}
NS_IMETHODIMP
nsDocumentFragment::SetPrefix(const nsAString& aPrefix)
{
return NS_ERROR_DOM_NAMESPACE_ERR;
}
NS_IMETHODIMP
nsDocumentFragment::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = nsnull;
nsresult rv = NS_OK;
nsCOMPtr<nsIDOMDocumentFragment> newFragment;
rv = NS_NewDocumentFragment(getter_AddRefs(newFragment), mOwnerDocument);
NS_ENSURE_SUCCESS(rv, rv);
if (aDeep) {
nsCOMPtr<nsIDOMNodeList> childNodes;
GetChildNodes(getter_AddRefs(childNodes));
if (childNodes) {
PRUint32 index, count;
childNodes->GetLength(&count);
for (index = 0; index < count; ++index) {
nsCOMPtr<nsIDOMNode> child;
childNodes->Item(index, getter_AddRefs(child));
if (child) {
nsCOMPtr<nsIDOMNode> newChild;
rv = child->CloneNode(PR_TRUE, getter_AddRefs(newChild));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> dummyNode;
rv = newFragment->AppendChild(newChild,
getter_AddRefs(dummyNode));
NS_ENSURE_SUCCESS(rv, rv);
}
} // End of for loop
} // if (childNodes)
} // if (aDeep)
return CallQueryInterface(newFragment, aReturn);
}
NS_IMPL_DOM_CLONENODE(nsDocumentFragment)
NS_IMETHODIMP
nsDocumentFragment::GetBaseURI(nsAString& aURI)

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

@ -275,6 +275,20 @@ nsGenericDOMDataNode::GetBaseURI(nsAString& aURI)
return NS_OK;
}
nsresult
nsGenericDOMDataNode::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
{
*aResult = nsnull;
nsIDocument *document = GetOwnerDoc();
nsCOMPtr<nsIContent> newContent;
nsresult rv = CloneContent(document, aDeep, getter_AddRefs(newContent));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(newContent, aResult);
}
nsresult
nsGenericDOMDataNode::LookupPrefix(const nsAString& aNamespaceURI,
nsAString& aPrefix)
@ -315,7 +329,7 @@ nsGenericDOMDataNode::LookupNamespaceURI(const nsAString& aNamespacePrefix,
// Implementation of nsIDOMCharacterData
nsresult
nsGenericDOMDataNode::GetData(nsAString& aData)
nsGenericDOMDataNode::GetData(nsAString& aData) const
{
if (mText.Is2b()) {
aData.Assign(mText.Get2b(), mText.GetLength());
@ -1039,11 +1053,11 @@ nsGenericDOMDataNode::SplitText(PRUint32 aOffset, nsIDOMText** aReturn)
}
/*
* Use CloneContent() for creating the new node so that the new node is of
* same class as this node!
* Use Clone for creating the new node so that the new node is of same class
* as this node!
*/
nsCOMPtr<nsITextContent> newContent = CloneContent(PR_FALSE, nsnull);
nsCOMPtr<nsITextContent> newContent = Clone(nsnull, PR_FALSE);
if (!newContent) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -1314,11 +1328,18 @@ nsGenericDOMDataNode::GetCurrentValueAtom()
return NS_NewAtom(val);
}
already_AddRefed<nsITextContent>
nsGenericDOMDataNode::CloneContent(PRBool aCloneText,
nsIDocument *aOwnerDocument)
nsresult
nsGenericDOMDataNode::CloneContent(nsIDocument *aOwnerDocument, PRBool aDeep,
nsIContent **aResult)
{
NS_ERROR("Huh, this shouldn't be called!");
// XXX We really want to pass the document to the constructor, but can't
// yet. See https://bugzilla.mozilla.org/show_bug.cgi?id=27382
*aResult = Clone(nsnull, PR_TRUE);
if (!*aResult) {
return NS_ERROR_OUT_OF_MEMORY;
}
return nsnull;
NS_ADDREF(*aResult);
return NS_OK;
}

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

@ -147,13 +147,23 @@ public:
const nsAString& aVersion,
PRBool* aReturn);
nsresult GetBaseURI(nsAString& aURI);
/**
* A basic implementation of the DOM cloneNode method. Calls CloneContent to
* do the actual cloning of the node.
*
* @param aDeep if true all descendants will be cloned too
* @param aResult the clone
*/
nsresult CloneNode(PRBool aDeep, nsIDOMNode **aResult);
nsresult LookupPrefix(const nsAString& aNamespaceURI,
nsAString& aPrefix);
nsresult LookupNamespaceURI(const nsAString& aNamespacePrefix,
nsAString& aNamespaceURI);
// Implementation for nsIDOMCharacterData
nsresult GetData(nsAString& aData);
nsresult GetData(nsAString& aData) const;
nsresult SetData(const nsAString& aData);
nsresult GetLength(PRUint32* aLength);
nsresult SubstringData(PRUint32 aOffset, PRUint32 aCount,
@ -243,6 +253,13 @@ public:
virtual nsresult RemoveChildAt(PRUint32 aIndex, PRBool aNotify);
virtual PRBool MayHaveFrame() const;
/**
* This calls Clone to do the actual cloning so that we end up with the
* right class for the clone.
*/
nsresult CloneContent(nsIDocument *aOwnerDocument, PRBool aDeep,
nsIContent **aResult);
// nsITextContent
virtual const nsTextFragment *Text();
virtual PRUint32 TextLength();
@ -256,9 +273,6 @@ public:
//----------------------------------------
virtual already_AddRefed<nsITextContent> CloneContent(PRBool aCloneText,
nsIDocument *aOwnerDocument);
#ifdef DEBUG
void ToCString(nsAString& aBuf, PRInt32 aOffset, PRInt32 aLen) const;
#endif
@ -266,6 +280,22 @@ public:
protected:
nsresult SplitText(PRUint32 aOffset, nsIDOMText** aReturn);
/**
* Method to clone this node. This needs to be overriden by all derived
* classes. If aCloneText is true the text content will be cloned too.
*
* @param aOwnerDocument the ownerDocument of the clone
* @param aCloneText if true the text content will be cloned too
* @return the clone
*/
virtual nsGenericDOMDataNode *Clone(nsIDocument *aOwnerDocument,
PRBool aCloneText)
{
NS_ERROR("This shouldn't be called!");
return nsnull;
}
nsTextFragment mText;
private:
@ -316,7 +346,8 @@ private:
*
* Note that classes using this macro will need to implement:
* NS_IMETHOD GetNodeType(PRUint16* aNodeType);
* NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
* nsGenericDOMDataNode *Clone(nsIDocument *aOwnerDocument,
* PRBool aCloneText);
*/
#define NS_IMPL_NSIDOMNODE_USING_GENERIC_DOM_DATA \
NS_IMETHOD GetNodeName(nsAString& aNodeName); \
@ -389,6 +420,10 @@ private:
PRBool* aReturn) { \
return nsGenericDOMDataNode::IsSupported(aFeature, aVersion, aReturn); \
} \
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn) { \
return nsGenericDOMDataNode::CloneNode(aDeep, aReturn); \
} \
virtual nsGenericDOMDataNode *Clone(nsIDocument *aOwnerDocument, \
PRBool aCloneText);
#endif /* nsGenericDOMDataNode_h___ */

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

@ -3401,11 +3401,13 @@ nsGenericElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) co
}
nsresult
nsGenericElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep)
nsGenericElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep) const
{
nsresult rv;
nsresult rv = NS_OK;
PRUint32 i, count = mAttrsAndChildren.AttrCount();
for (i = 0; i < count; ++i) {
// XXX Once we have access to existing nsDOMAttributes for this element, we
// should call CloneNode or ImportNode on them.
const nsAttrName* name = mAttrsAndChildren.GetSafeAttrNameAt(i);
const nsAttrValue* value = mAttrsAndChildren.AttrAt(i);
nsAutoString valStr;
@ -3415,21 +3417,63 @@ nsGenericElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep)
NS_ENSURE_SUCCESS(rv, rv);
}
if (!aDeep) {
return NS_OK;
if (aDeep) {
nsIDocument *doc = GetOwnerDoc();
nsIDocument *newDoc = aDst->GetOwnerDoc();
if (doc == newDoc) {
rv = CloneChildrenTo(aDst);
}
else {
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(newDoc);
rv = ImportChildrenTo(aDst, domDoc);
}
}
count = mAttrsAndChildren.ChildCount();
return rv;
}
nsresult
nsGenericElement::ImportChildrenTo(nsGenericElement *aDst,
nsIDOMDocument *aImportDocument) const
{
PRUint32 i, count = mAttrsAndChildren.ChildCount();
for (i = 0; i < count; ++i) {
nsresult rv;
nsCOMPtr<nsIDOMNode> node =
do_QueryInterface(mAttrsAndChildren.ChildAt(i));
NS_ASSERTION(node, "child doesn't implement nsIDOMNode");
do_QueryInterface(mAttrsAndChildren.ChildAt(i), &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> newNode;
rv = aImportDocument->ImportNode(node, PR_TRUE, getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> newContent = do_QueryInterface(newNode, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = aDst->AppendChildTo(newContent, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
nsGenericElement::CloneChildrenTo(nsGenericElement *aDst) const
{
PRUint32 i, count = mAttrsAndChildren.ChildCount();
for (i = 0; i < count; ++i) {
nsresult rv;
nsCOMPtr<nsIDOMNode> node =
do_QueryInterface(mAttrsAndChildren.ChildAt(i), &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> newNode;
rv = node->CloneNode(PR_TRUE, getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> newContent = do_QueryInterface(newNode);
nsCOMPtr<nsIContent> newContent = do_QueryInterface(newNode, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = aDst->AppendChildTo(newContent, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -3941,3 +3985,37 @@ nsGenericElement::UnsetProperty(nsIAtom *aPropertyName, nsresult *aStatus)
return doc->PropertyTable()->UnsetProperty(this, aPropertyName, aStatus);
}
nsresult
nsGenericElement::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
{
*aResult = nsnull;
nsIDocument *document = GetOwnerDoc();
nsCOMPtr<nsIContent> newContent;
nsresult rv = CloneContent(document, aDeep, getter_AddRefs(newContent));
NS_ENSURE_SUCCESS(rv, rv);
return CallQueryInterface(newContent, aResult);
}
nsresult
nsGenericElement::CloneContent(nsIDocument *aOwnerDocument, PRBool aDeep,
nsIContent **aResult)
{
if (GetOwnerDoc() == aOwnerDocument) {
return Clone(mNodeInfo, aDeep, aResult);
}
nsNodeInfoManager* nodeInfoManager = aOwnerDocument->NodeInfoManager();
nsCOMPtr<nsINodeInfo> newNodeInfo;
nsresult rv = nodeInfoManager->GetNodeInfo(mNodeInfo->NameAtom(),
mNodeInfo->GetPrefixAtom(),
mNodeInfo->NamespaceID(),
getter_AddRefs(newNodeInfo));
NS_ENSURE_SUCCESS(rv, rv);
return Clone(newNodeInfo, aDeep, aResult);
}

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

@ -445,6 +445,13 @@ public:
virtual void SetMayHaveFrame(PRBool aMayHaveFrame);
virtual PRBool MayHaveFrame() const;
/**
* This calls Clone to do the actual cloning so that we end up with the
* right class for the clone.
*/
nsresult CloneContent(nsIDocument *aOwnerDocument, PRBool aDeep,
nsIContent **aResult);
#ifdef DEBUG
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const;
@ -655,11 +662,28 @@ public:
protected:
/**
* Copy attributes and children from another content object
* @param aSrcContent the object to copy from
* Duplicate children by calling importNode and append them to another
* element.
*
* @param aDst the element to append the imported children to
* @param aImportDocument the document to use to call importNode
*/
nsresult ImportChildrenTo(nsGenericElement *aDst,
nsIDOMDocument *aImportDocument) const;
/**
* Clone children and append them to another element.
*
* @param aDst the element to append the imported children to
*/
nsresult CloneChildrenTo(nsGenericElement *aDst) const;
/**
* Copy attributes and children to another content object
* @param aDest the object to copy to
* @param aDeep whether to copy children
*/
nsresult CopyInnerTo(nsGenericElement* aDest, PRBool aDeep);
nsresult CopyInnerTo(nsGenericElement* aDest, PRBool aDeep) const;
/**
* Internal hook for converting an attribute name-string to an atomized name
@ -771,6 +795,37 @@ protected:
*/
void GetContentsAsText(nsAString& aText);
/**
* Method to clone this element. This needs to be overriden by all element
* classes. aNodeInfo should be identical to this element's nodeInfo, except
* for the document which may be different. If aDeep is true all descendants
* will be cloned too (by calling the DOM method cloneNode on them if the
* ownerDocument of aNodeInfo is the same as the ownerDocument of this
* element or by calling the DOM method importNode if they differ).
*
* @param aNodeInfo the nodeinfo to use for the clone
* @param aDeep if true all descendants will be cloned too (attributes are
* always cloned)
* @param aResult the clone
*/
virtual nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult)
{
NS_ERROR("This shouldn't be called!");
return NS_ERROR_NOT_IMPLEMENTED;
}
/**
* A basic implementation of the DOM cloneNode method. Calls CloneContent to
* do the actual cloning of the element.
*
* @param aDeep if true all descendants will be cloned too (attributes on the
* element are always cloned)
* @param aResult the clone
*/
nsresult CloneNode(PRBool aDeep, nsIDOMNode **aResult);
/**
* Information about this type of node
*/
@ -900,56 +955,65 @@ public:
NS_IMETHOD HasAttributes(PRBool* aReturn) { \
return _to HasAttributes(aReturn); \
} \
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn); \
virtual nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep, \
nsIContent **aResult);
/**
* Macros to implement CloneNode().
*/
#define NS_IMPL_DOM_CLONENODE(_elementName) \
NS_IMPL_DOM_CLONENODE_AMBIGUOUS(_elementName, nsIDOMNode)
#define NS_IMPL_DOM_CLONENODE_AMBIGUOUS(_elementName, _implClass) \
NS_IMETHODIMP \
_elementName::CloneNode(PRBool aDeep, nsIDOMNode **aResult) \
nsresult \
_elementName::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep, \
nsIContent **aResult) \
{ \
*aResult = nsnull; \
\
_elementName *it = new _elementName(mNodeInfo); \
_elementName *it = new _elementName(aNodeInfo); \
if (!it) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
\
nsCOMPtr<nsIDOMNode> kungFuDeathGrip = NS_STATIC_CAST(_implClass*, it); \
\
nsCOMPtr<nsIContent> kungFuDeathGrip = it; \
nsresult rv = CopyInnerTo(it, aDeep); \
if (NS_SUCCEEDED(rv)) { \
kungFuDeathGrip.swap(*aResult); \
} \
\
return rv; \
}
#define NS_IMPL_DOM_CLONENODE_WITH_INIT(_elementName) \
} \
NS_IMETHODIMP \
_elementName::CloneNode(PRBool aDeep, nsIDOMNode **aResult) \
{ \
return nsGenericElement::CloneNode(aDeep, aResult); \
}
#define NS_IMPL_DOM_CLONENODE_WITH_INIT(_elementName) \
nsresult \
_elementName::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep, \
nsIContent **aResult) \
{ \
*aResult = nsnull; \
\
_elementName *it = new _elementName(mNodeInfo); \
_elementName *it = new _elementName(aNodeInfo); \
if (!it) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
\
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it); \
\
nsCOMPtr<nsIContent> kungFuDeathGrip = it; \
nsresult rv = it->Init(); \
\
rv |= CopyInnerTo(it, aDeep); \
if (NS_SUCCEEDED(rv)) { \
kungFuDeathGrip.swap(*aResult); \
} \
\
return rv; \
} \
NS_IMETHODIMP \
_elementName::CloneNode(PRBool aDeep, nsIDOMNode **aResult) \
{ \
return nsGenericElement::CloneNode(aDeep, aResult); \
}
#endif /* nsGenericElement_h___ */

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

@ -74,9 +74,6 @@ public:
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out, PRInt32 aIndent, PRBool aDumpAll) const;
#endif
virtual already_AddRefed<nsITextContent> CloneContent(PRBool aCloneText,
nsIDocument *aOwnerDocument);
};
/**
@ -112,7 +109,7 @@ public:
nsITextContent* mContent; // Weak ref; it owns us
};
nsAttributeTextNode() : nsTextNode(nsnull) {
nsAttributeTextNode(nsIDocument *aDocument) : nsTextNode(aDocument) {
}
virtual ~nsAttributeTextNode() {
DetachListener();
@ -124,6 +121,17 @@ public:
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
PRBool aNullParent = PR_TRUE);
virtual nsGenericDOMDataNode *Clone(nsIDocument *aOwnerDocument,
PRBool aCloneText)
{
nsAttributeTextNode *it = new nsAttributeTextNode(aOwnerDocument);
if (it && aCloneText) {
it->mText = mText;
}
return it;
}
nsRefPtr<nsAttrChangeListener> mListener; // our listener
private:
void DetachListener();
@ -197,37 +205,23 @@ nsTextNode::GetNodeType(PRUint16* aNodeType)
return NS_OK;
}
NS_IMETHODIMP
nsTextNode::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
nsCOMPtr<nsITextContent> textContent = CloneContent(PR_TRUE, GetOwnerDoc());
NS_ENSURE_TRUE(textContent, NS_ERROR_OUT_OF_MEMORY);
return CallQueryInterface(textContent, aReturn);
}
already_AddRefed<nsITextContent>
nsTextNode::CloneContent(PRBool aCloneText, nsIDocument *aOwnerDocument)
{
nsTextNode* it = new nsTextNode(nsnull);
if (!it)
return nsnull;
if (aCloneText) {
it->mText = mText;
}
NS_ADDREF(it);
return it;
}
PRBool
nsTextNode::IsContentOfType(PRUint32 aFlags) const
{
return !(aFlags & ~eTEXT);
}
nsGenericDOMDataNode*
nsTextNode::Clone(nsIDocument *aOwnerDocument, PRBool aCloneText)
{
nsTextNode *it = new nsTextNode(aOwnerDocument);
if (it && aCloneText) {
it->mText = mText;
}
return it;
}
#ifdef DEBUG
void
nsTextNode::List(FILE* out, PRInt32 aIndent) const
@ -304,15 +298,15 @@ nsAttributeTextNode::nsAttrChangeListener::HandleEvent(nsIDOMEvent* aEvent)
}
nsresult
NS_NewAttributeContent(PRInt32 aNameSpaceID, nsIAtom* aAttrName,
nsIContent** aResult)
NS_NewAttributeContent(nsIDocument *aOwnerDoc, PRInt32 aNameSpaceID,
nsIAtom* aAttrName, nsIContent** aResult)
{
NS_PRECONDITION(aAttrName, "Must have an attr name");
NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "Must know namespace");
*aResult = nsnull;
nsRefPtr<nsAttributeTextNode> textNode = new nsAttributeTextNode();
nsRefPtr<nsAttributeTextNode> textNode = new nsAttributeTextNode(aOwnerDoc);
NS_ENSURE_TRUE(textNode, NS_ERROR_OUT_OF_MEMORY);
textNode->mListener =

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

@ -271,53 +271,47 @@ nsGenericHTMLElement::Shutdown()
}
nsresult
nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep)
nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep) const
{
nsresult rv = NS_OK;
PRInt32 i, count = GetAttrCount();
nsCOMPtr<nsIAtom> name, prefix;
PRInt32 namespace_id;
nsAutoString value;
for (i = 0; i < count; ++i) {
rv = GetAttrNameAt(i, &namespace_id, getter_AddRefs(name),
getter_AddRefs(prefix));
NS_ENSURE_SUCCESS(rv, rv);
if (name == nsHTMLAtoms::style && namespace_id == kNameSpaceID_None) {
// XXX Once we have access to existing nsDOMAttributes for this element, we
// should call CloneNode or ImportNode on them.
const nsAttrName *name = mAttrsAndChildren.GetSafeAttrNameAt(i);
const nsAttrValue *value = mAttrsAndChildren.AttrAt(i);
if (name->Equals(nsHTMLAtoms::style, kNameSpaceID_None) &&
value->Type() == nsAttrValue::eCSSStyleRule) {
// We can't just set this as a string, because that will fail
// to reparse the string into style data until the node is
// inserted into the document. Clone the HTMLValue instead.
const nsAttrValue* styleVal =
mAttrsAndChildren.GetAttr(nsHTMLAtoms::style);
if (styleVal && styleVal->Type() == nsAttrValue::eCSSStyleRule) {
nsCOMPtr<nsICSSRule> ruleClone;
rv = styleVal->GetCSSStyleRuleValue()->
Clone(*getter_AddRefs(ruleClone));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsICSSRule> ruleClone;
rv = value->GetCSSStyleRuleValue()->Clone(*getter_AddRefs(ruleClone));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsICSSStyleRule> styleRule = do_QueryInterface(ruleClone);
NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsICSSStyleRule> styleRule = do_QueryInterface(ruleClone);
NS_ENSURE_TRUE(styleRule, NS_ERROR_UNEXPECTED);
rv = aDst->SetInlineStyleRule(styleRule, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
rv = aDst->SetInlineStyleRule(styleRule, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
continue;
}
continue;
}
rv = GetAttr(namespace_id, name, value);
NS_ENSURE_SUCCESS(rv, rv);
rv = aDst->SetAttr(namespace_id, name, prefix, value, PR_FALSE);
nsAutoString valStr;
value->ToString(valStr);
rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
name->GetPrefix(), valStr, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
nsIDocument *doc = nsContentUtils::GetDocument(mNodeInfo);
nsIDocument *newDoc = aDst->GetOwnerDoc();
PRInt32 id;
if (doc) {
id = doc->GetAndIncrementContentID();
if (newDoc) {
id = newDoc->GetAndIncrementContentID();
} else {
id = PR_INT32_MAX;
}
@ -325,25 +319,17 @@ nsGenericHTMLElement::CopyInnerTo(nsGenericElement* aDst, PRBool aDeep)
aDst->SetContentID(id);
if (aDeep) {
PRInt32 i;
PRInt32 count = mAttrsAndChildren.ChildCount();
for (i = 0; i < count; ++i) {
nsCOMPtr<nsIDOMNode> node =
do_QueryInterface(mAttrsAndChildren.ChildAt(i));
NS_ASSERTION(node, "child doesn't implement nsIDOMNode");
nsCOMPtr<nsIDOMNode> newNode;
rv = node->CloneNode(aDeep, getter_AddRefs(newNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> newContent(do_QueryInterface(newNode));
NS_ASSERTION(newContent, "clone doesn't implement nsIContent");
rv = aDst->AppendChildTo(newContent, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
nsIDocument *doc = GetOwnerDoc();
if (doc == newDoc) {
rv = CloneChildrenTo(aDst);
}
else {
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(newDoc);
rv = ImportChildrenTo(aDst, domDoc);
}
}
return NS_OK;
return rv;
}
nsresult

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

@ -105,7 +105,7 @@ public:
void **aInstancePtr);
// From nsGenericElement
nsresult CopyInnerTo(nsGenericElement* aDest, PRBool aDeep);
nsresult CopyInnerTo(nsGenericElement* aDest, PRBool aDeep) const;
// Implementation for nsIDOMNode
NS_METHOD GetNodeName(nsAString& aNodeName);

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

@ -386,18 +386,19 @@ NS_HTML_CONTENT_INTERFACE_MAP_END
// nsIDOMNode
nsresult
nsHTMLInputElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsHTMLInputElement::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult)
{
*aReturn = nsnull;
*aResult = nsnull;
nsHTMLInputElement* it = new nsHTMLInputElement(mNodeInfo, PR_FALSE);
nsHTMLInputElement *it = new nsHTMLInputElement(aNodeInfo, PR_FALSE);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
CopyInnerTo(it, aDeep);
nsCOMPtr<nsIContent> kungFuDeathGrip = it;
nsresult rv = CopyInnerTo(it, aDeep);
NS_ENSURE_SUCCESS(rv, rv);
switch (mType) {
case NS_FORM_INPUT_TEXT:
@ -425,12 +426,17 @@ nsHTMLInputElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
default:
break;
}
kungFuDeathGrip.swap(*aReturn);
kungFuDeathGrip.swap(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLInputElement::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
{
return nsGenericElement::CloneNode(aDeep, aResult);
}
void
nsHTMLInputElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,

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

@ -114,8 +114,7 @@ NS_HTML_CONTENT_INTERFACE_MAP_AMBIGOUS_BEGIN(nsHTMLSharedListElement,
NS_HTML_CONTENT_INTERFACE_MAP_END
NS_IMPL_DOM_CLONENODE_AMBIGUOUS(nsHTMLSharedListElement,
nsIDOMHTMLOListElement)
NS_IMPL_DOM_CLONENODE(nsHTMLSharedListElement)
NS_IMPL_BOOL_ATTR(nsHTMLSharedListElement, Compact, compact)

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

@ -485,18 +485,19 @@ nsHTMLScriptElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
}
nsresult
nsHTMLScriptElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult)
{
*aReturn = nsnull;
*aResult = nsnull;
nsHTMLScriptElement* it = new nsHTMLScriptElement(mNodeInfo, PR_FALSE);
nsHTMLScriptElement* it = new nsHTMLScriptElement(aNodeInfo, PR_FALSE);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
CopyInnerTo(it, aDeep);
nsCOMPtr<nsIContent> kungFuDeathGrip = it;
nsresult rv = CopyInnerTo(it, aDeep);
NS_ENSURE_SUCCESS(rv, rv);
// The clone should be marked evaluated if we are. It should also be marked
// evaluated if we're evaluating, to handle the case when this script node's
@ -504,11 +505,17 @@ nsHTMLScriptElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
it->mIsEvaluated = mIsEvaluated || mEvaluating;
it->mLineNumber = mLineNumber;
kungFuDeathGrip.swap(*aReturn);
kungFuDeathGrip.swap(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsHTMLScriptElement::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
{
return nsGenericElement::CloneNode(aDeep, aResult);
}
NS_IMETHODIMP
nsHTMLScriptElement::GetText(nsAString& aValue)
{

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

@ -198,7 +198,7 @@ NS_HTML_CONTENT_INTERFACE_MAP_AMBIGOUS_BEGIN(nsHTMLSharedElement,
NS_HTML_CONTENT_INTERFACE_MAP_END
NS_IMPL_DOM_CLONENODE_AMBIGUOUS(nsHTMLSharedElement, nsIDOMHTMLEmbedElement)
NS_IMPL_DOM_CLONENODE(nsHTMLSharedElement)
/////////////////////////////////////////////

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

@ -124,7 +124,9 @@ public:
nsHTMLUnknownElement(nsINodeInfo *aNodeInfo);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult);
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode **aResult);
};
NS_INTERFACE_MAP_BEGIN(nsHTMLUnknownElement)

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

@ -86,7 +86,7 @@ public:
PRBool aNotify);
protected:
// Dummy init method to make the NS_IMPL_NS_NEW_SVG_ELEMENT and
// NS_IMPL_SVG_DOM_CLONENODE usable with this class. This should be
// NS_IMPL_DOM_CLONENODE_WITH_INIT usable with this class. This should be
// completely optimized away.
inline nsresult Init()
{

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

@ -71,11 +71,6 @@ public:
virtual void List(FILE* out, PRInt32 aIndent) const;
virtual void DumpContent(FILE* out, PRInt32 aIndent,PRBool aDumpAll) const;
#endif
virtual already_AddRefed<nsITextContent> CloneContent(PRBool aCloneText,
nsIDocument *aOwnerDocument);
protected:
};
nsresult
@ -154,28 +149,14 @@ nsXMLCDATASection::GetNodeType(PRUint16* aNodeType)
return NS_OK;
}
NS_IMETHODIMP
nsXMLCDATASection::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsGenericDOMDataNode*
nsXMLCDATASection::Clone(nsIDocument *aOwnerDocument, PRBool aCloneText)
{
nsCOMPtr<nsITextContent> textContent = CloneContent(PR_TRUE, GetOwnerDoc());
NS_ENSURE_TRUE(textContent, NS_ERROR_OUT_OF_MEMORY);
return CallQueryInterface(textContent, aReturn);
}
already_AddRefed<nsITextContent>
nsXMLCDATASection::CloneContent(PRBool aCloneText, nsIDocument *aOwnerDocument)
{
nsXMLCDATASection* it = new nsXMLCDATASection(nsnull);
if (!it)
return nsnull;
if (aCloneText) {
nsXMLCDATASection* it = new nsXMLCDATASection(aOwnerDocument);
if (it && aCloneText) {
it->mText = mText;
}
NS_ADDREF(it);
return it;
}

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

@ -166,24 +166,14 @@ nsXMLProcessingInstruction::GetNodeType(PRUint16* aNodeType)
return NS_OK;
}
NS_IMETHODIMP
nsXMLProcessingInstruction::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsGenericDOMDataNode*
nsXMLProcessingInstruction::Clone(nsIDocument *aOwnerDocument,
PRBool aCloneText)
{
nsAutoString data;
GetData(data);
nsIDocument *document = GetOwnerDoc();
// We really want to pass the document here, but can't yet. Waiting
// on BindToTree.
nsXMLProcessingInstruction *pi =
new nsXMLProcessingInstruction(mTarget, data, nsnull);
if (!pi) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aReturn = pi);
return NS_OK;
return new nsXMLProcessingInstruction(mTarget, data, aOwnerDocument);
}
#ifdef DEBUG

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

@ -59,7 +59,6 @@ public:
// nsIDOMNode
NS_IMETHOD SetNodeValue(const nsAString& aData);
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
// nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -78,6 +77,8 @@ protected:
nsAString& aType,
nsAString& aMedia,
PRBool* aIsAlternate);
virtual nsGenericDOMDataNode* Clone(nsIDocument *aOwnerDocument,
PRBool aCloneText);
};
// nsISupports implementation
@ -141,22 +142,6 @@ nsXMLStylesheetPI::SetNodeValue(const nsAString& aNodeValue)
return rv;
}
NS_IMETHODIMP
nsXMLStylesheetPI::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
nsAutoString data;
GetData(data);
nsXMLStylesheetPI *pi = new nsXMLStylesheetPI(data, nsnull);
if (!pi) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aReturn = pi);
return NS_OK;
}
// nsStyleLinkElement
NS_IMETHODIMP
@ -249,6 +234,15 @@ nsXMLStylesheetPI::GetStyleSheetInfo(nsAString& aTitle,
return;
}
nsGenericDOMDataNode*
nsXMLStylesheetPI::Clone(nsIDocument *aOwnerDocument, PRBool aCloneText)
{
nsAutoString data;
GetData(data);
return new nsXMLStylesheetPI(data, aOwnerDocument);
}
nsresult
NS_NewXMLStylesheetProcessingInstruction(nsIContent** aInstancePtrResult,
const nsAString& aData,

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

@ -422,22 +422,20 @@ nsXTFElementWrapper::IntrinsicState() const
return mIntrinsicState;
}
//----------------------------------------------------------------------
// nsIDOMNode methods:
NS_IMETHODIMP
nsXTFElementWrapper::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
nsresult
nsXTFElementWrapper::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult)
{
*aResult = nsnull;
nsCOMPtr<nsIContent> it;
nsContentUtils::GetXTFService()->CreateElement(getter_AddRefs(it),
mNodeInfo);
aNodeInfo);
if (!it)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIDOMNode> kungFuDeathGrip(do_QueryInterface(it));
nsXTFElementWrapper* wrapper =
NS_STATIC_CAST(nsXTFElementWrapper*, NS_STATIC_CAST(nsIContent*, it.get()));
NS_STATIC_CAST(nsXTFElementWrapper*,
NS_STATIC_CAST(nsIContent*, it.get()));
nsresult rv = CopyInnerTo(wrapper, aDeep);
if (NS_SUCCEEDED(rv)) {
@ -454,7 +452,7 @@ nsXTFElementWrapper::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
}
}
}
kungFuDeathGrip.swap(*aResult);
it.swap(*aResult);
}
wrapper->CloneState(this);

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

@ -105,9 +105,6 @@ public:
virtual void BeginAddingChildren();
virtual void DoneAddingChildren();
// nsIDOMNode specializations:
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode **aResult);
// nsIDOMElement specializations:
NS_IMETHOD GetAttribute(const nsAString& aName,
nsAString& aReturn);
@ -126,6 +123,8 @@ public:
{
return GetXTFElement()->CloneState(aElement);
}
nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult);
protected:
// to be implemented by subclasses:

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

@ -154,9 +154,6 @@
#include "nsIControllers.h"
// The XUL interfaces implemented by the RDF content node.
#include "nsIDOMXULElement.h"
// The XUL doc interface
#include "nsIDOMXULDocument.h"
@ -345,7 +342,6 @@ PRUint32 nsXULPrototypeAttribute::gNumCacheFills;
nsXULElement::nsXULElement(nsINodeInfo* aNodeInfo)
: nsGenericElement(aNodeInfo),
mPrototype(nsnull),
mBindingParent(nsnull)
{
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements);
@ -364,11 +360,32 @@ nsXULElement::~nsXULElement()
if (slots) {
NS_IF_RELEASE(slots->mControllers); // Forces release
}
if (mPrototype)
mPrototype->Release();
}
/* static */
already_AddRefed<nsXULElement>
nsXULElement::Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
PRBool aIsScriptable)
{
nsXULElement *element = new nsXULElement(aNodeInfo);
if (element) {
NS_ADDREF(element);
element->mPrototype = aPrototype;
if (aIsScriptable) {
// Check each attribute on the prototype to see if we need to do
// any additional processing and hookup that would otherwise be
// done 'automagically' by SetAttr().
for (PRUint32 i = 0; i < aPrototype->mNumAttributes; ++i) {
element->AddListenerFor(aPrototype->mAttributes[i].mName,
PR_TRUE);
}
}
}
return element;
}
nsresult
nsXULElement::Create(nsXULPrototypeElement* aPrototype,
@ -396,27 +413,19 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype,
NS_ENSURE_SUCCESS(rv, rv);
}
else {
nodeInfo = aPrototype->mNodeInfo;
nodeInfo = aPrototype->mNodeInfo;
}
nsRefPtr<nsXULElement> element = new nsXULElement(nodeInfo);
if (! element)
nsRefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
aIsScriptable);
if (!element) {
return NS_ERROR_OUT_OF_MEMORY;
}
element->mPrototype = aPrototype;
aPrototype->AddRef();
if (aIsScriptable) {
// Check each attribute on the prototype to see if we need to do
// any additional processing and hookup that would otherwise be
// done 'automagically' by SetAttr().
for (PRUint32 i = 0; i < aPrototype->mNumAttributes; ++i)
element->AddListenerFor(aPrototype->mAttributes[i].mName, PR_TRUE);
}
NS_ADDREF(*aResult = element.get());
return NS_OK;
}
@ -431,10 +440,7 @@ NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo)
nsXULElement* element = new nsXULElement(aNodeInfo);
NS_ENSURE_TRUE(element, NS_ERROR_OUT_OF_MEMORY);
// Using kungFuDeathGrip so an early return will clean up properly.
nsCOMPtr<nsIContent> kungFuDeathGrip = element;
kungFuDeathGrip.swap(*aResult);
NS_ADDREF(*aResult = element);
#ifdef DEBUG_ATTRIBUTE_STATS
{
@ -501,12 +507,11 @@ nsXULElement::QueryInterface(REFNSIID aIID, void** aInstancePtr)
//----------------------------------------------------------------------
// nsIDOMNode interface
NS_IMETHODIMP
nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
nsresult
nsXULElement::Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
nsIContent **aResult)
{
nsresult rv;
nsCOMPtr<nsIContent> result;
*aResult = nsnull;
// XXX setting document on some nodes not in a document so XBL will bind
// and chrome won't break. Make XBL bind to document-less nodes!
@ -522,26 +527,18 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
PRBool fakeBeingInDocument = PR_TRUE;
// If we have a prototype, so will our clone.
nsRefPtr<nsXULElement> element;
if (mPrototype) {
rv = nsXULElement::Create(mPrototype, GetOwnerDoc(), PR_TRUE,
getter_AddRefs(result));
NS_ENSURE_SUCCESS(rv, rv);
element = nsXULElement::Create(mPrototype, aNodeInfo, PR_TRUE);
fakeBeingInDocument = IsInDoc();
} else {
rv = NS_NewXULElement(getter_AddRefs(result), mNodeInfo);
NS_ENSURE_SUCCESS(rv, rv);
}
else {
element = new nsXULElement(aNodeInfo);
}
// Copy attributes
PRInt32 count = mAttrsAndChildren.AttrCount();
for (PRInt32 i = 0; i < count; ++i) {
const nsAttrName* name = mAttrsAndChildren.GetSafeAttrNameAt(i);
nsAutoString valStr;
mAttrsAndChildren.AttrAt(i)->ToString(valStr);
rv = result->SetAttr(name->NamespaceID(), name->LocalName(),
name->GetPrefix(), valStr, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
if (!element) {
return NS_ERROR_OUT_OF_MEMORY;
}
// XXX TODO: set up RDF generic builder n' stuff if there is a
@ -551,44 +548,24 @@ nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
// Note that we're _not_ copying mControllers.
if (aDeep) {
// Copy cloned children!
PRInt32 i, count = mAttrsAndChildren.ChildCount();
for (i = 0; i < count; ++i) {
nsIContent* child = mAttrsAndChildren.ChildAt(i);
NS_ASSERTION(child != nsnull, "null ptr");
if (! child)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIDOMNode> domchild = do_QueryInterface(child);
NS_ASSERTION(domchild != nsnull, "child is not a DOM node");
if (! domchild)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIDOMNode> newdomchild;
rv = domchild->CloneNode(PR_TRUE, getter_AddRefs(newdomchild));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIContent> newchild = do_QueryInterface(newdomchild);
NS_ASSERTION(newchild != nsnull, "newdomchild is not an nsIContent");
if (! newchild)
return NS_ERROR_UNEXPECTED;
rv = result->AppendChildTo(newchild, PR_FALSE);
if (NS_FAILED(rv)) return rv;
}
nsresult rv = CopyInnerTo(element, aDeep);
if (NS_SUCCEEDED(rv)) {
NS_ADDREF(*aResult = element);
}
if (fakeBeingInDocument) {
// Don't use BindToTree here so we don't confuse the descendant
// non-XUL nodes.
NS_STATIC_CAST(nsXULElement*,
NS_STATIC_CAST(nsIContent*, result.get()))->
mParentPtrBits |= PARENT_BIT_INDOCUMENT;
element->mParentPtrBits |= PARENT_BIT_INDOCUMENT;
}
return CallQueryInterface(result, aReturn);
return rv;
}
NS_IMETHODIMP
nsXULElement::CloneNode(PRBool aDeep, nsIDOMNode **aResult)
{
return nsGenericElement::CloneNode(aDeep, aResult);
}
//----------------------------------------------------------------------

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

@ -588,7 +588,7 @@ protected:
protected:
// Required fields
nsXULPrototypeElement* mPrototype;
nsRefPtr<nsXULPrototypeElement> mPrototype;
nsCOMPtr<nsIEventListenerManager> mListenerManager; // [OWNER]
/**
@ -645,6 +645,10 @@ protected:
friend nsresult
NS_NewXULElement(nsIContent** aResult, nsINodeInfo *aNodeInfo);
static already_AddRefed<nsXULElement>
Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
PRBool aIsScriptable);
};

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

@ -2064,7 +2064,7 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIFrame* aParentFram
nsresult rv = NS_ERROR_FAILURE;
if (attrName) {
nsIFrame* textFrame = nsnull;
rv = NS_NewAttributeContent(attrNameSpace, attrName,
rv = NS_NewAttributeContent(mDocument, attrNameSpace, attrName,
getter_AddRefs(content));
NS_ENSURE_SUCCESS(rv, rv);

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

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