Added nsDocumentFragment to build. Fixed bug 1256 - the content sink is flushed as soon as it encounters a script tag.

git-svn-id: svn://10.0.0.236/trunk@15407 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
vidur%netscape.com
1998-11-28 23:51:06 +00:00
parent e7ca2be12c
commit bf493acab1
9 changed files with 450 additions and 49 deletions

View File

@@ -247,6 +247,7 @@ public:
nsresult GrowStack();
nsresult AddText(const nsString& aText);
nsresult FlushText(PRBool* aDidFlush = nsnull);
nsresult FlushTags();
void MaybeMarkSinkDirty();
@@ -1150,6 +1151,29 @@ SinkContext::AddText(const nsString& aText)
return NS_OK;
}
/**
* Flush all elements that have been seen so far such that
* they are visible in the tree. Specifically, make sure
* that they are all added to their respective parents.
*/
nsresult
SinkContext::FlushTags()
{
FlushText();
PRInt32 stackPos = mStackPos-1;
while ((stackPos > 0) && (0 == (mStack[stackPos].mFlags & APPENDED))) {
nsIHTMLContent* content = mStack[stackPos].mContent;
nsIHTMLContent* parent = mStack[stackPos-1].mContent;
parent->AppendChildTo(content, PR_FALSE);
mStack[stackPos].mFlags |= APPENDED;
stackPos--;
}
return NS_OK;
}
/**
* Flush any buffered text out by creating a text content object and
* adding it to the content.
@@ -2280,7 +2304,9 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
// Otherwise, get the text content of the script tag
script = aNode.GetSkippedContent();
}
mCurrentContext->FlushTags();
if (script != "") {
nsIScriptContextOwner *owner;
nsIScriptContext *context;

View File

@@ -391,6 +391,77 @@ nsHTMLDocument::SetDTDMode(nsDTDMode aMode)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLDocument::ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIContent* child;
nsIAtom *name;
aContainer->GetTag(name);
aContainer->ChildAt(aNewIndexInContainer, child);
RegisterNamedItems(aContainer, name == nsHTMLAtoms::form);
NS_IF_RELEASE(child);
NS_IF_RELEASE(name);
}
return nsDocument::ContentAppended(aContainer, aNewIndexInContainer);
}
NS_IMETHODIMP
nsHTMLDocument::ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIAtom *name;
aContainer->GetTag(name);
RegisterNamedItems(aChild, name == nsHTMLAtoms::form);
NS_IF_RELEASE(name);
}
return nsDocument::ContentInserted(aContainer, aChild, aIndexInContainer);
}
NS_IMETHODIMP
nsHTMLDocument::ContentReplaced(nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIAtom *name;
aContainer->GetTag(name);
UnregisterNamedItems(aOldChild, name == nsHTMLAtoms::form);
RegisterNamedItems(aNewChild, name == nsHTMLAtoms::form);
NS_IF_RELEASE(name);
}
return nsDocument::ContentReplaced(aContainer, aOldChild,
aNewChild, aIndexInContainer);
}
NS_IMETHODIMP
nsHTMLDocument::ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIAtom *name;
aContainer->GetTag(name);
UnregisterNamedItems(aChild, name == nsHTMLAtoms::form);
NS_IF_RELEASE(name);
}
return nsDocument::ContentRemoved(aContainer, aChild, aIndexInContainer);
}
//
// nsIDOMDocument interface implementation
//
@@ -934,28 +1005,68 @@ nsHTMLDocument::DeleteNamedItems()
}
}
void
nsHTMLDocument::RegisterNamedItems(nsIContent *aContent, PRBool aInForm)
static PRBool
IsNamedItem(nsIContent* aContent, nsIAtom *aTag,
PRBool aInForm, nsString& aName)
{
static nsAutoString name("NAME");
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
// Only the content types reflected in Level 0 with a NAME
// attribute are registered. Images and forms always get
// reflected up to the document. Applets and embeds only go
// to the closest container (which could be a form).
if ((tag == nsHTMLAtoms::img) || (tag == nsHTMLAtoms::form) ||
(!aInForm && ((tag == nsHTMLAtoms::applet) ||
(tag == nsHTMLAtoms::embed)))) {
if (NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(name, value)) {
char *nameStr = value.ToNewCString();
PL_HashTableAdd(mNamedItems, nameStr, aContent);
if ((aTag == nsHTMLAtoms::img) || (aTag == nsHTMLAtoms::form) ||
(!aInForm && ((aTag == nsHTMLAtoms::applet) ||
(aTag == nsHTMLAtoms::embed)))) {
if (NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(name, aName)) {
return PR_TRUE;
}
}
return PR_FALSE;
}
void
nsHTMLDocument::UnregisterNamedItems(nsIContent *aContent, PRBool aInForm)
{
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
if (IsNamedItem(aContent, tag, aInForm, value)) {
char *nameStr = value.ToNewCString();
// XXX What about the string held in the hash table entry
PL_HashTableRemove(mNamedItems, nameStr);
delete [] nameStr;
}
inForm = aInForm || (tag == nsHTMLAtoms::form);
NS_IF_RELEASE(tag);
PRInt32 i, count;
aContent->ChildCount(count);
for (i = 0; i < count; i++) {
nsIContent *child;
aContent->ChildAt(i, child);
UnregisterNamedItems(child, inForm);
NS_RELEASE(child);
}
}
void
nsHTMLDocument::RegisterNamedItems(nsIContent *aContent, PRBool aInForm)
{
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
if (IsNamedItem(aContent, tag, aInForm, value)) {
char *nameStr = value.ToNewCString();
PL_HashTableAdd(mNamedItems, nameStr, aContent);
}
inForm = aInForm || (tag == nsHTMLAtoms::form);
NS_IF_RELEASE(tag);
@@ -969,22 +1080,68 @@ nsHTMLDocument::RegisterNamedItems(nsIContent *aContent, PRBool aInForm)
}
}
nsIContent*
nsHTMLDocument::FindNamedItem(nsIContent *aContent,
const nsString& aName,
PRBool aInForm)
{
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
if (IsNamedItem(aContent, tag, aInForm, value)) {
if (aName.Equals(value)) {
NS_IF_RELEASE(tag);
return aContent;
}
}
inForm = aInForm || (tag == nsHTMLAtoms::form);
NS_IF_RELEASE(tag);
PRInt32 i, count;
nsIContent *result = nsnull;
aContent->ChildCount(count);
for (i = 0; (i < count) && (nsnull == result); i++) {
nsIContent *child;
aContent->ChildAt(i, child);
result = FindNamedItem(child, aName, inForm);
NS_RELEASE(child);
}
return result;
}
NS_IMETHODIMP
nsHTMLDocument::NamedItem(const nsString& aName, nsIDOMElement** aReturn)
{
static nsAutoString name("NAME");
nsresult result = NS_OK;
nsIContent *content;
nsIContent *content = nsnull;
if (nsnull == mNamedItems) {
mNamedItems = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
PL_CompareValues, nsnull, nsnull);
RegisterNamedItems(mRootContent, PR_FALSE);
// XXX If we have a parser, it means that we're still loading the
// document. Since there's still content coming in (and not all
// may yet have been explicitly added to the document), we do
// a depth-first search rather than build up a table.
// Obviously, this may be inefficient for large documents.
if (nsnull != mParser) {
content = FindNamedItem(mRootContent, aName, PR_FALSE);
}
else {
// If the document has completed loading, we build a table and
// cache the named items. The table will be updated as content
// is added and removed.
if (nsnull == mNamedItems) {
mNamedItems = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
PL_CompareValues, nsnull, nsnull);
RegisterNamedItems(mRootContent, PR_FALSE);
}
char *str = aName.ToNewCString();
content = (nsIContent *)PL_HashTableLookup(mNamedItems, str);
delete [] str;
}
char *str = aName.ToNewCString();
content = (nsIContent *)PL_HashTableLookup(mNamedItems, str);
if (nsnull != content) {
result = content->QueryInterface(kIDOMElementIID, (void **)aReturn);
}
@@ -992,7 +1149,6 @@ nsHTMLDocument::NamedItem(const nsString& aName, nsIDOMElement** aReturn)
*aReturn = nsnull;
}
delete [] str;
return result;
}

View File

@@ -60,6 +60,19 @@ public:
NS_IMETHOD GetDTDMode(nsDTDMode& aMode);
NS_IMETHOD SetDTDMode(nsDTDMode aMode);
NS_IMETHOD ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
NS_IMETHOD ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
NS_IMETHOD ContentReplaced(nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer);
NS_IMETHOD ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
// nsIDOMDocument interface
NS_IMETHOD GetDoctype(nsIDOMDocumentType** aDocumentType);
NS_IMETHOD GetImplementation(nsIDOMDOMImplementation** aImplementation)
@@ -138,6 +151,10 @@ protected:
protected:
static PRIntn RemoveStrings(PLHashEntry *he, PRIntn i, void *arg);
void RegisterNamedItems(nsIContent *aContent, PRBool aInForm);
void UnregisterNamedItems(nsIContent *aContent, PRBool aInForm);
nsIContent* FindNamedItem(nsIContent *aContent, const nsString& aName,
PRBool aInForm);
void DeleteNamedItems();
nsIContent *MatchName(nsIContent *aContent, const nsString& aName);

View File

@@ -29,6 +29,7 @@ DEFINES += -D_IMPL_NS_LAYOUT
CPPSRCS = \
nsContentList.cpp \
nsDocument.cpp \
nsDocumentFragment.cpp \
nsFrameImageLoader.cpp \
nsGalleyContext.cpp \
nsPresContext.cpp \
@@ -53,7 +54,7 @@ EXPORTS = \
nsXIFConverter.h \
$(NULL)
INCLUDES += -I../../html/base/src
INCLUDES += -I../../html/base/src -I../../html/content/src
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))

View File

@@ -23,6 +23,7 @@ DEFINES=-D_IMPL_NS_LAYOUT -DWIN32_LEAN_AND_MEAN
CPPSRCS = \
nsContentList.cpp \
nsDocument.cpp \
nsDocumentFragment.cpp \
nsFrameImageLoader.cpp \
nsGalleyContext.cpp \
nsPresContext.cpp \
@@ -45,6 +46,7 @@ EXPORTS=nsSelectionRange.h nsSelectionPoint.h
CPP_OBJS= \
.\$(OBJDIR)\nsContentList.obj \
.\$(OBJDIR)\nsDocument.obj \
.\$(OBJDIR)\nsDocumentFragment.obj \
.\$(OBJDIR)\nsFrameImageLoader.obj \
.\$(OBJDIR)\nsGalleyContext.obj \
.\$(OBJDIR)\nsPresContext.obj \
@@ -62,7 +64,7 @@ CPP_OBJS= \
LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor \
-I$(PUBLIC)\dom -I$(PUBLIC)\js -I$(PUBLIC)\netlib \
-I$(PUBLIC)\pref -I..\..\html\base\src
-I$(PUBLIC)\pref -I..\..\html\base\src -I..\..\html\content\src
LCFLAGS = \
$(LCFLAGS) \

View File

@@ -96,7 +96,7 @@ private:
// Another helper class that implements the nsIDOMNamedNodeMap interface.
class nsDOMAttributeMap : public nsIDOMNamedNodeMap,
public nsIScriptObjectOwner
public nsIScriptObjectOwner
{
public:
nsDOMAttributeMap(nsIContent* aContent);

View File

@@ -247,6 +247,7 @@ public:
nsresult GrowStack();
nsresult AddText(const nsString& aText);
nsresult FlushText(PRBool* aDidFlush = nsnull);
nsresult FlushTags();
void MaybeMarkSinkDirty();
@@ -1150,6 +1151,29 @@ SinkContext::AddText(const nsString& aText)
return NS_OK;
}
/**
* Flush all elements that have been seen so far such that
* they are visible in the tree. Specifically, make sure
* that they are all added to their respective parents.
*/
nsresult
SinkContext::FlushTags()
{
FlushText();
PRInt32 stackPos = mStackPos-1;
while ((stackPos > 0) && (0 == (mStack[stackPos].mFlags & APPENDED))) {
nsIHTMLContent* content = mStack[stackPos].mContent;
nsIHTMLContent* parent = mStack[stackPos-1].mContent;
parent->AppendChildTo(content, PR_FALSE);
mStack[stackPos].mFlags |= APPENDED;
stackPos--;
}
return NS_OK;
}
/**
* Flush any buffered text out by creating a text content object and
* adding it to the content.
@@ -2280,7 +2304,9 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
// Otherwise, get the text content of the script tag
script = aNode.GetSkippedContent();
}
mCurrentContext->FlushTags();
if (script != "") {
nsIScriptContextOwner *owner;
nsIScriptContext *context;

View File

@@ -391,6 +391,77 @@ nsHTMLDocument::SetDTDMode(nsDTDMode aMode)
return NS_OK;
}
NS_IMETHODIMP
nsHTMLDocument::ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIContent* child;
nsIAtom *name;
aContainer->GetTag(name);
aContainer->ChildAt(aNewIndexInContainer, child);
RegisterNamedItems(aContainer, name == nsHTMLAtoms::form);
NS_IF_RELEASE(child);
NS_IF_RELEASE(name);
}
return nsDocument::ContentAppended(aContainer, aNewIndexInContainer);
}
NS_IMETHODIMP
nsHTMLDocument::ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIAtom *name;
aContainer->GetTag(name);
RegisterNamedItems(aChild, name == nsHTMLAtoms::form);
NS_IF_RELEASE(name);
}
return nsDocument::ContentInserted(aContainer, aChild, aIndexInContainer);
}
NS_IMETHODIMP
nsHTMLDocument::ContentReplaced(nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIAtom *name;
aContainer->GetTag(name);
UnregisterNamedItems(aOldChild, name == nsHTMLAtoms::form);
RegisterNamedItems(aNewChild, name == nsHTMLAtoms::form);
NS_IF_RELEASE(name);
}
return nsDocument::ContentReplaced(aContainer, aOldChild,
aNewChild, aIndexInContainer);
}
NS_IMETHODIMP
nsHTMLDocument::ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
if (nsnull != mNamedItems) {
nsIAtom *name;
aContainer->GetTag(name);
UnregisterNamedItems(aChild, name == nsHTMLAtoms::form);
NS_IF_RELEASE(name);
}
return nsDocument::ContentRemoved(aContainer, aChild, aIndexInContainer);
}
//
// nsIDOMDocument interface implementation
//
@@ -934,28 +1005,68 @@ nsHTMLDocument::DeleteNamedItems()
}
}
void
nsHTMLDocument::RegisterNamedItems(nsIContent *aContent, PRBool aInForm)
static PRBool
IsNamedItem(nsIContent* aContent, nsIAtom *aTag,
PRBool aInForm, nsString& aName)
{
static nsAutoString name("NAME");
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
// Only the content types reflected in Level 0 with a NAME
// attribute are registered. Images and forms always get
// reflected up to the document. Applets and embeds only go
// to the closest container (which could be a form).
if ((tag == nsHTMLAtoms::img) || (tag == nsHTMLAtoms::form) ||
(!aInForm && ((tag == nsHTMLAtoms::applet) ||
(tag == nsHTMLAtoms::embed)))) {
if (NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(name, value)) {
char *nameStr = value.ToNewCString();
PL_HashTableAdd(mNamedItems, nameStr, aContent);
if ((aTag == nsHTMLAtoms::img) || (aTag == nsHTMLAtoms::form) ||
(!aInForm && ((aTag == nsHTMLAtoms::applet) ||
(aTag == nsHTMLAtoms::embed)))) {
if (NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(name, aName)) {
return PR_TRUE;
}
}
return PR_FALSE;
}
void
nsHTMLDocument::UnregisterNamedItems(nsIContent *aContent, PRBool aInForm)
{
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
if (IsNamedItem(aContent, tag, aInForm, value)) {
char *nameStr = value.ToNewCString();
// XXX What about the string held in the hash table entry
PL_HashTableRemove(mNamedItems, nameStr);
delete [] nameStr;
}
inForm = aInForm || (tag == nsHTMLAtoms::form);
NS_IF_RELEASE(tag);
PRInt32 i, count;
aContent->ChildCount(count);
for (i = 0; i < count; i++) {
nsIContent *child;
aContent->ChildAt(i, child);
UnregisterNamedItems(child, inForm);
NS_RELEASE(child);
}
}
void
nsHTMLDocument::RegisterNamedItems(nsIContent *aContent, PRBool aInForm)
{
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
if (IsNamedItem(aContent, tag, aInForm, value)) {
char *nameStr = value.ToNewCString();
PL_HashTableAdd(mNamedItems, nameStr, aContent);
}
inForm = aInForm || (tag == nsHTMLAtoms::form);
NS_IF_RELEASE(tag);
@@ -969,22 +1080,68 @@ nsHTMLDocument::RegisterNamedItems(nsIContent *aContent, PRBool aInForm)
}
}
nsIContent*
nsHTMLDocument::FindNamedItem(nsIContent *aContent,
const nsString& aName,
PRBool aInForm)
{
nsAutoString value;
nsIAtom *tag;
aContent->GetTag(tag);
PRBool inForm;
if (IsNamedItem(aContent, tag, aInForm, value)) {
if (aName.Equals(value)) {
NS_IF_RELEASE(tag);
return aContent;
}
}
inForm = aInForm || (tag == nsHTMLAtoms::form);
NS_IF_RELEASE(tag);
PRInt32 i, count;
nsIContent *result = nsnull;
aContent->ChildCount(count);
for (i = 0; (i < count) && (nsnull == result); i++) {
nsIContent *child;
aContent->ChildAt(i, child);
result = FindNamedItem(child, aName, inForm);
NS_RELEASE(child);
}
return result;
}
NS_IMETHODIMP
nsHTMLDocument::NamedItem(const nsString& aName, nsIDOMElement** aReturn)
{
static nsAutoString name("NAME");
nsresult result = NS_OK;
nsIContent *content;
nsIContent *content = nsnull;
if (nsnull == mNamedItems) {
mNamedItems = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
PL_CompareValues, nsnull, nsnull);
RegisterNamedItems(mRootContent, PR_FALSE);
// XXX If we have a parser, it means that we're still loading the
// document. Since there's still content coming in (and not all
// may yet have been explicitly added to the document), we do
// a depth-first search rather than build up a table.
// Obviously, this may be inefficient for large documents.
if (nsnull != mParser) {
content = FindNamedItem(mRootContent, aName, PR_FALSE);
}
else {
// If the document has completed loading, we build a table and
// cache the named items. The table will be updated as content
// is added and removed.
if (nsnull == mNamedItems) {
mNamedItems = PL_NewHashTable(10, PL_HashString, PL_CompareStrings,
PL_CompareValues, nsnull, nsnull);
RegisterNamedItems(mRootContent, PR_FALSE);
}
char *str = aName.ToNewCString();
content = (nsIContent *)PL_HashTableLookup(mNamedItems, str);
delete [] str;
}
char *str = aName.ToNewCString();
content = (nsIContent *)PL_HashTableLookup(mNamedItems, str);
if (nsnull != content) {
result = content->QueryInterface(kIDOMElementIID, (void **)aReturn);
}
@@ -992,7 +1149,6 @@ nsHTMLDocument::NamedItem(const nsString& aName, nsIDOMElement** aReturn)
*aReturn = nsnull;
}
delete [] str;
return result;
}

View File

@@ -60,6 +60,19 @@ public:
NS_IMETHOD GetDTDMode(nsDTDMode& aMode);
NS_IMETHOD SetDTDMode(nsDTDMode aMode);
NS_IMETHOD ContentAppended(nsIContent* aContainer,
PRInt32 aNewIndexInContainer);
NS_IMETHOD ContentInserted(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
NS_IMETHOD ContentReplaced(nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer);
NS_IMETHOD ContentRemoved(nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer);
// nsIDOMDocument interface
NS_IMETHOD GetDoctype(nsIDOMDocumentType** aDocumentType);
NS_IMETHOD GetImplementation(nsIDOMDOMImplementation** aImplementation)
@@ -138,6 +151,10 @@ protected:
protected:
static PRIntn RemoveStrings(PLHashEntry *he, PRIntn i, void *arg);
void RegisterNamedItems(nsIContent *aContent, PRBool aInForm);
void UnregisterNamedItems(nsIContent *aContent, PRBool aInForm);
nsIContent* FindNamedItem(nsIContent *aContent, const nsString& aName,
PRBool aInForm);
void DeleteNamedItems();
nsIContent *MatchName(nsIContent *aContent, const nsString& aName);