Fix for bug 38349. Implemented nsIDOMNode::CloneNode() and ImportNode() for XML and HTML documents as part of finishing out our DOM1 and DOM2 implementations. Cleanup of DOMImplementation::createDocument. r=jst

This commit is contained in:
vidur%netscape.com 2000-06-21 23:56:52 +00:00
Родитель 76698ef605
Коммит d690a7d2b9
14 изменённых файлов: 226 добавлений и 99 удалений

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

@ -25,7 +25,7 @@
#include "nsISupports.h"
class nsIDocument;
class nsIURI;
/*
* Event listener manager interface.
@ -40,7 +40,7 @@ class nsIPrivateDOMImplementation : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IPRIVATEDOMIMPLEMENTATION_IID; return iid; }
NS_IMETHOD Init(nsIDocument* aDoc) = 0;
NS_IMETHOD Init(nsIURI* aBaseURI) = 0;
};
NS_LAYOUT nsresult

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

@ -361,7 +361,7 @@ class nsDOMImplementation : public nsIDOMDOMImplementation,
public nsIPrivateDOMImplementation
{
public:
nsDOMImplementation(nsIDocument* aDocument = nsnull);
nsDOMImplementation(nsIURI* aBaseURI = nsnull);
virtual ~nsDOMImplementation();
NS_DECL_ISUPPORTS
@ -385,11 +385,11 @@ public:
NS_IMETHOD SetScriptObject(void *aScriptObject);
//nsIPrivateDOMImplementation
NS_IMETHOD Init(nsIDocument* aDoc);
NS_IMETHOD Init(nsIURI* aBaseURI);
protected:
void *mScriptObject;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsIURI> mBaseURI;
};
@ -402,11 +402,11 @@ NS_NewDOMImplementation(nsIDOMDOMImplementation** aInstancePtrResult)
return domImpl->QueryInterface(NS_GET_IID(nsIDOMDOMImplementation), (void**) aInstancePtrResult);
}
nsDOMImplementation::nsDOMImplementation(nsIDocument* aDocument)
nsDOMImplementation::nsDOMImplementation(nsIURI* aBaseURI)
{
NS_INIT_REFCNT();
mScriptObject = nsnull;
mDocument = aDocument;
mBaseURI = aBaseURI;
}
nsDOMImplementation::~nsDOMImplementation()
@ -447,15 +447,8 @@ nsDOMImplementation::CreateDocument(const nsString& aNamespaceURI,
nsresult rv = NS_OK;
*aReturn = nsnull;
nsIURI* baseURI = nsnull;
if (mDocument) {
rv = mDocument->GetBaseURL(baseURI);
if (NS_FAILED(rv)) return rv;
}
NS_NewDOMDocument(aReturn, aNamespaceURI, aQualifiedName, aDoctype, mBaseURI);
NS_NewDOMDocument(aReturn, aNamespaceURI, aQualifiedName, aDoctype, baseURI);
NS_IF_RELEASE(baseURI);
return rv;
}
@ -490,9 +483,9 @@ nsDOMImplementation::SetScriptObject(void *aScriptObject)
}
NS_IMETHODIMP
nsDOMImplementation::Init(nsIDocument* aDoc)
nsDOMImplementation::Init(nsIURI* aBaseURI)
{
mDocument = aDoc;
mBaseURI = aBaseURI;
return NS_OK;
}
@ -2062,7 +2055,7 @@ nsDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
{
// For now, create a new implementation every time. This shouldn't
// be a high bandwidth operation
nsDOMImplementation* impl = new nsDOMImplementation(this);
nsDOMImplementation* impl = new nsDOMImplementation(mDocumentURL);
if (nsnull == impl) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -2247,6 +2240,17 @@ nsDocument::CreateElementWithNameSpace(const nsString& aTagName,
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
{
NS_ENSURE_ARG(aImportedNode);
NS_ENSURE_ARG_POINTER(aReturn);
return aImportedNode->CloneNode(aDeep, aReturn);
}
NS_IMETHODIMP
nsDocument::AddBinding(nsIDOMElement* aContent, const nsString& aURL)
{
@ -2466,6 +2470,7 @@ nsDocument::GetHeight(PRInt32* aHeight)
NS_IMETHODIMP
nsDocument::Load (const nsString& aUrl)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -2677,6 +2682,7 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNod
aNewChild->GetNodeType(&nodeType);
if ((COMMENT_NODE != nodeType) &&
(TEXT_NODE != nodeType) &&
(PROCESSING_INSTRUCTION_NODE != nodeType) &&
(DOCUMENT_TYPE_NODE != nodeType) &&
(ELEMENT_NODE != nodeType)) {
@ -2764,6 +2770,7 @@ nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNod
aNewChild->GetNodeType(&nodeType);
if ((COMMENT_NODE != nodeType) &&
(TEXT_NODE != nodeType) &&
(PROCESSING_INSTRUCTION_NODE != nodeType) &&
(DOCUMENT_TYPE_NODE != nodeType) &&
(ELEMENT_NODE != nodeType)) {
@ -2894,7 +2901,7 @@ nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
NS_IMETHODIMP
nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
// We don't allow cloning of a document
// XXX should be implemented by subclass
*aReturn = nsnull;
return NS_OK;
}
@ -2902,8 +2909,16 @@ nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMETHODIMP
nsDocument::Normalize()
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
// XXX Not completely correct, since you can still have unnormalized
// text nodes as immediate children of the document.
if (mRootContent) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mRootContent);
if (node) {
return node->Normalize();
}
}
return NS_OK;
}
NS_IMETHODIMP

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

@ -390,6 +390,9 @@ public:
NS_IMETHOD GetElementsByTagNameNS(const nsString& aNamespaceURI, const nsString& aLocalName, nsIDOMNodeList** aReturn);
NS_IMETHOD GetStyleSheets(nsIDOMStyleSheetList** aStyleSheets);
NS_IMETHOD GetCharacterSet(nsString& aCharacterSet);
NS_IMETHOD ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn);
NS_IMETHOD CreateElementWithNameSpace(const nsString& aTagName,
const nsString& aNameSpace,
nsIDOMElement** aReturn);

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

@ -2233,8 +2233,7 @@ nsHTMLDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
return nsDocument::ImportNode(aImportedNode, aDeep, aReturn);
}
NS_IMETHODIMP

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

@ -785,14 +785,82 @@ nsXMLDocument::CreateElementWithNameSpace(const nsString& aTagName,
return rv;
}
NS_IMETHODIMP
nsXMLDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = nsnull;
nsresult rv;
nsCOMPtr<nsIDOMDocumentType> docType, newDocType;
nsCOMPtr<nsIDOMDocument> newDoc;
// Get the doctype prior to new document construction. There's no big
// advantage now to dealing with the doctype separately, but maybe one
// day we'll do something significant with the doctype on document creation.
GetDoctype(getter_AddRefs(docType));
if (docType) {
nsCOMPtr<nsIDOMNode> newDocTypeNode;
rv = docType->CloneNode(PR_TRUE, getter_AddRefs(newDocTypeNode));
if (NS_FAILED(rv)) return rv;
newDocType = do_QueryInterface(newDocTypeNode);
}
// Create an empty document
nsAutoString emptyStr;
emptyStr.Truncate();
rv = NS_NewDOMDocument(getter_AddRefs(newDoc), emptyStr, emptyStr,
newDocType, mDocumentURL);
if (NS_FAILED(rv)) return rv;
if (aDeep) {
// If there was a doctype, a new one has already been inserted into the
// new document. We might have to add nodes before it.
PRBool beforeDocType = (docType.get() != nsnull);
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 && (child != docType)) {
nsCOMPtr<nsIDOMNode> newChild;
rv = child->CloneNode(aDeep, getter_AddRefs(newChild));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMNode> dummyNode;
if (beforeDocType) {
rv = newDoc->InsertBefore(newChild,
docType,
getter_AddRefs(dummyNode));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
else {
rv = newDoc->AppendChild(newChild,
getter_AddRefs(dummyNode));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
}
else {
beforeDocType = PR_FALSE;
}
}
}
}
return newDoc->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)aReturn);
}
NS_IMETHODIMP
nsXMLDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
return nsDocument::ImportNode(aImportedNode, aDeep, aReturn);
}
NS_IMETHODIMP

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

@ -59,6 +59,9 @@ public:
NS_IMETHOD EndLoad();
// nsIDOMNode interface
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
// nsIDOMDocument interface
NS_IMETHOD GetDoctype(nsIDOMDocumentType** aDocumentType);
NS_IMETHOD CreateCDATASection(const nsString& aData, nsIDOMCDATASection** aReturn);

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

@ -2445,7 +2445,7 @@ nsXULDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
nsCOMPtr<nsIPrivateDOMImplementation> impl = do_QueryInterface(*aImplementation, &rv);
if (NS_FAILED(rv)) return rv;
rv = impl->Init((nsIDocument*) this);
rv = impl->Init(mDocumentURL);
return rv;
}

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

@ -1,49 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef nsIPrivateDOMImplementation_h__
#define nsIPrivateDOMImplementation_h__
#include "nsISupports.h"
class nsIDocument;
/*
* Event listener manager interface.
*/
#define NS_IPRIVATEDOMIMPLEMENTATION_IID \
{ /* d3205fb8-2652-11d4-ba06-0060b0fc76dd */ \
0xd3205fb8, 0x2652, 0x11d4, \
{0xba, 0x06, 0x00, 0x60, 0xb0, 0xfc, 0x76, 0xdd} }
class nsIPrivateDOMImplementation : public nsISupports {
public:
static const nsIID& GetIID() { static nsIID iid = NS_IPRIVATEDOMIMPLEMENTATION_IID; return iid; }
NS_IMETHOD Init(nsIDocument* aDoc) = 0;
};
NS_LAYOUT nsresult
NS_NewDOMImplementation(nsIDOMDOMImplementation** aInstancePtrResult);
#endif // nsIPrivateDOMImplementation_h__

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

@ -361,7 +361,7 @@ class nsDOMImplementation : public nsIDOMDOMImplementation,
public nsIPrivateDOMImplementation
{
public:
nsDOMImplementation(nsIDocument* aDocument = nsnull);
nsDOMImplementation(nsIURI* aBaseURI = nsnull);
virtual ~nsDOMImplementation();
NS_DECL_ISUPPORTS
@ -385,11 +385,11 @@ public:
NS_IMETHOD SetScriptObject(void *aScriptObject);
//nsIPrivateDOMImplementation
NS_IMETHOD Init(nsIDocument* aDoc);
NS_IMETHOD Init(nsIURI* aBaseURI);
protected:
void *mScriptObject;
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsIURI> mBaseURI;
};
@ -402,11 +402,11 @@ NS_NewDOMImplementation(nsIDOMDOMImplementation** aInstancePtrResult)
return domImpl->QueryInterface(NS_GET_IID(nsIDOMDOMImplementation), (void**) aInstancePtrResult);
}
nsDOMImplementation::nsDOMImplementation(nsIDocument* aDocument)
nsDOMImplementation::nsDOMImplementation(nsIURI* aBaseURI)
{
NS_INIT_REFCNT();
mScriptObject = nsnull;
mDocument = aDocument;
mBaseURI = aBaseURI;
}
nsDOMImplementation::~nsDOMImplementation()
@ -447,15 +447,8 @@ nsDOMImplementation::CreateDocument(const nsString& aNamespaceURI,
nsresult rv = NS_OK;
*aReturn = nsnull;
nsIURI* baseURI = nsnull;
if (mDocument) {
rv = mDocument->GetBaseURL(baseURI);
if (NS_FAILED(rv)) return rv;
}
NS_NewDOMDocument(aReturn, aNamespaceURI, aQualifiedName, aDoctype, mBaseURI);
NS_NewDOMDocument(aReturn, aNamespaceURI, aQualifiedName, aDoctype, baseURI);
NS_IF_RELEASE(baseURI);
return rv;
}
@ -490,9 +483,9 @@ nsDOMImplementation::SetScriptObject(void *aScriptObject)
}
NS_IMETHODIMP
nsDOMImplementation::Init(nsIDocument* aDoc)
nsDOMImplementation::Init(nsIURI* aBaseURI)
{
mDocument = aDoc;
mBaseURI = aBaseURI;
return NS_OK;
}
@ -2062,7 +2055,7 @@ nsDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
{
// For now, create a new implementation every time. This shouldn't
// be a high bandwidth operation
nsDOMImplementation* impl = new nsDOMImplementation(this);
nsDOMImplementation* impl = new nsDOMImplementation(mDocumentURL);
if (nsnull == impl) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -2247,6 +2240,17 @@ nsDocument::CreateElementWithNameSpace(const nsString& aTagName,
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
{
NS_ENSURE_ARG(aImportedNode);
NS_ENSURE_ARG_POINTER(aReturn);
return aImportedNode->CloneNode(aDeep, aReturn);
}
NS_IMETHODIMP
nsDocument::AddBinding(nsIDOMElement* aContent, const nsString& aURL)
{
@ -2466,6 +2470,7 @@ nsDocument::GetHeight(PRInt32* aHeight)
NS_IMETHODIMP
nsDocument::Load (const nsString& aUrl)
{
// Should be implemented by subclass
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -2677,6 +2682,7 @@ nsDocument::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNod
aNewChild->GetNodeType(&nodeType);
if ((COMMENT_NODE != nodeType) &&
(TEXT_NODE != nodeType) &&
(PROCESSING_INSTRUCTION_NODE != nodeType) &&
(DOCUMENT_TYPE_NODE != nodeType) &&
(ELEMENT_NODE != nodeType)) {
@ -2764,6 +2770,7 @@ nsDocument::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNod
aNewChild->GetNodeType(&nodeType);
if ((COMMENT_NODE != nodeType) &&
(TEXT_NODE != nodeType) &&
(PROCESSING_INSTRUCTION_NODE != nodeType) &&
(DOCUMENT_TYPE_NODE != nodeType) &&
(ELEMENT_NODE != nodeType)) {
@ -2894,7 +2901,7 @@ nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
NS_IMETHODIMP
nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
// We don't allow cloning of a document
// XXX should be implemented by subclass
*aReturn = nsnull;
return NS_OK;
}
@ -2902,8 +2909,16 @@ nsDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
NS_IMETHODIMP
nsDocument::Normalize()
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
// XXX Not completely correct, since you can still have unnormalized
// text nodes as immediate children of the document.
if (mRootContent) {
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(mRootContent);
if (node) {
return node->Normalize();
}
}
return NS_OK;
}
NS_IMETHODIMP

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

@ -390,6 +390,9 @@ public:
NS_IMETHOD GetElementsByTagNameNS(const nsString& aNamespaceURI, const nsString& aLocalName, nsIDOMNodeList** aReturn);
NS_IMETHOD GetStyleSheets(nsIDOMStyleSheetList** aStyleSheets);
NS_IMETHOD GetCharacterSet(nsString& aCharacterSet);
NS_IMETHOD ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn);
NS_IMETHOD CreateElementWithNameSpace(const nsString& aTagName,
const nsString& aNameSpace,
nsIDOMElement** aReturn);

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

@ -2233,8 +2233,7 @@ nsHTMLDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
return nsDocument::ImportNode(aImportedNode, aDeep, aReturn);
}
NS_IMETHODIMP

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

@ -785,14 +785,82 @@ nsXMLDocument::CreateElementWithNameSpace(const nsString& aTagName,
return rv;
}
NS_IMETHODIMP
nsXMLDocument::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
{
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = nsnull;
nsresult rv;
nsCOMPtr<nsIDOMDocumentType> docType, newDocType;
nsCOMPtr<nsIDOMDocument> newDoc;
// Get the doctype prior to new document construction. There's no big
// advantage now to dealing with the doctype separately, but maybe one
// day we'll do something significant with the doctype on document creation.
GetDoctype(getter_AddRefs(docType));
if (docType) {
nsCOMPtr<nsIDOMNode> newDocTypeNode;
rv = docType->CloneNode(PR_TRUE, getter_AddRefs(newDocTypeNode));
if (NS_FAILED(rv)) return rv;
newDocType = do_QueryInterface(newDocTypeNode);
}
// Create an empty document
nsAutoString emptyStr;
emptyStr.Truncate();
rv = NS_NewDOMDocument(getter_AddRefs(newDoc), emptyStr, emptyStr,
newDocType, mDocumentURL);
if (NS_FAILED(rv)) return rv;
if (aDeep) {
// If there was a doctype, a new one has already been inserted into the
// new document. We might have to add nodes before it.
PRBool beforeDocType = (docType.get() != nsnull);
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 && (child != docType)) {
nsCOMPtr<nsIDOMNode> newChild;
rv = child->CloneNode(aDeep, getter_AddRefs(newChild));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIDOMNode> dummyNode;
if (beforeDocType) {
rv = newDoc->InsertBefore(newChild,
docType,
getter_AddRefs(dummyNode));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
else {
rv = newDoc->AppendChild(newChild,
getter_AddRefs(dummyNode));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
}
else {
beforeDocType = PR_FALSE;
}
}
}
}
return newDoc->QueryInterface(NS_GET_IID(nsIDOMNode), (void**)aReturn);
}
NS_IMETHODIMP
nsXMLDocument::ImportNode(nsIDOMNode* aImportedNode,
PRBool aDeep,
nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me");
return NS_ERROR_NOT_IMPLEMENTED;
return nsDocument::ImportNode(aImportedNode, aDeep, aReturn);
}
NS_IMETHODIMP

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

@ -59,6 +59,9 @@ public:
NS_IMETHOD EndLoad();
// nsIDOMNode interface
NS_IMETHOD CloneNode(PRBool aDeep, nsIDOMNode** aReturn);
// nsIDOMDocument interface
NS_IMETHOD GetDoctype(nsIDOMDocumentType** aDocumentType);
NS_IMETHOD CreateCDATASection(const nsString& aData, nsIDOMCDATASection** aReturn);

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

@ -2445,7 +2445,7 @@ nsXULDocument::GetImplementation(nsIDOMDOMImplementation** aImplementation)
nsCOMPtr<nsIPrivateDOMImplementation> impl = do_QueryInterface(*aImplementation, &rv);
if (NS_FAILED(rv)) return rv;
rv = impl->Init((nsIDocument*) this);
rv = impl->Init(mDocumentURL);
return rv;
}