Bug 574089 - Optimize ::GetInnerHTML, r=jst

--HG--
extra : rebase_source : 3ed1549eaa96d3ff3fe6bf2bb2562dd9e68fcc17
This commit is contained in:
Olli Pettay 2010-06-26 23:39:56 +03:00
parent fb86d46cf9
commit f48d7a4a08
10 changed files with 191 additions and 60 deletions

View File

@ -63,6 +63,7 @@
#include "nsSMILAnimationController.h" #include "nsSMILAnimationController.h"
#endif // MOZ_SMIL #endif // MOZ_SMIL
#include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObject.h"
#include "nsIDocumentEncoder.h"
class nsIContent; class nsIContent;
class nsPresContext; class nsPresContext;
@ -116,10 +117,9 @@ class Element;
} // namespace mozilla } // namespace mozilla
// fbcd570b-dbfa-479b-9bd0-02312129c044
#define NS_IDOCUMENT_IID \ #define NS_IDOCUMENT_IID \
{ 0xfbcd570b, 0xdbfa, 0x479b, \ { 0x1d8bd3d4, 0x6f6d, 0x49fe, \
{ 0x9b, 0xd0, 0x02, 0x31, 0x21, 0x29, 0xc0, 0x44 } } { 0xaf, 0xda, 0xc9, 0x4a, 0xef, 0x8f, 0xcf, 0x1f } }
// Flag for AddStyleSheet(). // Flag for AddStyleSheet().
#define NS_STYLESHEET_FROM_CATALOG (1 << 0) #define NS_STYLESHEET_FROM_CATALOG (1 << 0)
@ -1115,6 +1115,16 @@ public:
// Do nothing. // Do nothing.
} }
already_AddRefed<nsIDocumentEncoder> GetCachedEncoder()
{
return mCachedEncoder.forget();
}
void SetCachedEncoder(nsIDocumentEncoder* aEncoder)
{
mCachedEncoder = aEncoder;
}
// In case of failure, the document really can't initialize the frame loader. // In case of failure, the document really can't initialize the frame loader.
virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) = 0; virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) = 0;
// In case of failure, the caller must handle the error, for example by // In case of failure, the caller must handle the error, for example by
@ -1422,6 +1432,17 @@ protected:
return GetRootElement(); return GetRootElement();
} }
void SetContentTypeInternal(const nsACString& aType)
{
mCachedEncoder = nsnull;
mContentType = aType;
}
nsCString GetContentTypeInternal() const
{
return mContentType;
}
nsCOMPtr<nsIURI> mDocumentURI; nsCOMPtr<nsIURI> mDocumentURI;
nsCOMPtr<nsIURI> mDocumentBaseURI; nsCOMPtr<nsIURI> mDocumentBaseURI;
@ -1530,7 +1551,9 @@ protected:
PRUint32 mBidiOptions; PRUint32 mBidiOptions;
nsCString mContentLanguage; nsCString mContentLanguage;
private:
nsCString mContentType; nsCString mContentType;
protected:
// The document's security info // The document's security info
nsCOMPtr<nsISupports> mSecurityInfo; nsCOMPtr<nsISupports> mSecurityInfo;
@ -1560,6 +1583,8 @@ protected:
// Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow, // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
// updated on every set of mSecriptGlobalObject. // updated on every set of mSecriptGlobalObject.
nsPIDOMWindow *mWindow; nsPIDOMWindow *mWindow;
nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID) NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)

View File

@ -44,6 +44,13 @@ interface nsISelection;
interface nsIDOMNode; interface nsIDOMNode;
interface nsIOutputStream; interface nsIOutputStream;
%{ C++
class nsINode;
class nsIDocument;
%}
[ptr] native nsINodePtr(nsINode);
[ptr] native nsIDocumentPtr(nsIDocument);
[scriptable, uuid(c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d)] [scriptable, uuid(c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d)]
interface nsIDocumentEncoderNodeFixup : nsISupports interface nsIDocumentEncoderNodeFixup : nsISupports
{ {
@ -61,7 +68,7 @@ interface nsIDocumentEncoderNodeFixup : nsISupports
nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids); nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids);
}; };
[scriptable, uuid(794a81f6-bde6-4f76-9f5e-0ea0911a2d9f)] [scriptable, uuid(7222bdf1-c2b9-41f1-a40a-a3d65283a95b)]
interface nsIDocumentEncoder : nsISupports interface nsIDocumentEncoder : nsISupports
{ {
// Output methods flag bits. There are a frightening number of these, // Output methods flag bits. There are a frightening number of these,
@ -238,6 +245,9 @@ interface nsIDocumentEncoder : nsISupports
void init(in nsIDOMDocument aDocument, void init(in nsIDOMDocument aDocument,
in AString aMimeType, in AString aMimeType,
in unsigned long aFlags); in unsigned long aFlags);
[noscript] void nativeInit(in nsIDocumentPtr aDocument,
in AString aMimeType,
in unsigned long aFlags);
/** /**
* If the selection is set to a non-null value, then the * If the selection is set to a non-null value, then the
@ -270,6 +280,7 @@ interface nsIDocumentEncoder : nsISupports
* @param aContainer The node which child nodes will be encoded. * @param aContainer The node which child nodes will be encoded.
*/ */
void setContainerNode(in nsIDOMNode aContainer); void setContainerNode(in nsIDOMNode aContainer);
[noscript] void setNativeContainerNode(in nsINodePtr aContainer);
/** /**
* Documents typically have an intrinsic character set, * Documents typically have an intrinsic character set,

View File

@ -1393,7 +1393,7 @@ nsDOMImplementation::Init(nsIURI* aDocumentURI, nsIURI* aBaseURI,
nsDocument::nsDocument(const char* aContentType) nsDocument::nsDocument(const char* aContentType)
: nsIDocument() : nsIDocument()
{ {
mContentType = aContentType; SetContentTypeInternal(nsDependentCString(aContentType));
#ifdef PR_LOGGING #ifdef PR_LOGGING
if (!gDocumentLeakPRLog) if (!gDocumentLeakPRLog)
@ -1688,6 +1688,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstBaseNodeWithHref) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstBaseNodeWithHref)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMImplementation) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMImplementation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder)
// Traverse all our nsCOMArrays. // Traverse all our nsCOMArrays.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mStyleSheets)
@ -1731,6 +1732,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstBaseNodeWithHref)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMImplementation) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDOMImplementation)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
@ -1947,7 +1949,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
mLastModified.Truncate(); mLastModified.Truncate();
// XXXbz I guess we're assuming that the caller will either pass in // XXXbz I guess we're assuming that the caller will either pass in
// a channel with a useful type or call SetContentType? // a channel with a useful type or call SetContentType?
mContentType.Truncate(); SetContentTypeInternal(EmptyCString());
mContentLanguage.Truncate(); mContentLanguage.Truncate();
mBaseTarget.Truncate(); mBaseTarget.Truncate();
mReferrer.Truncate(); mReferrer.Truncate();
@ -2155,7 +2157,7 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
contentType.EndReading(end); contentType.EndReading(end);
semicolon = start; semicolon = start;
FindCharInReadable(';', semicolon, end); FindCharInReadable(';', semicolon, end);
mContentType = Substring(start, semicolon); SetContentTypeInternal(Substring(start, semicolon));
} }
RetrieveRelevantHeaders(aChannel); RetrieveRelevantHeaders(aChannel);
@ -2436,7 +2438,7 @@ nsDocument::SetApplicationCache(nsIApplicationCache *aApplicationCache)
NS_IMETHODIMP NS_IMETHODIMP
nsDocument::GetContentType(nsAString& aContentType) nsDocument::GetContentType(nsAString& aContentType)
{ {
CopyUTF8toUTF16(mContentType, aContentType); CopyUTF8toUTF16(GetContentTypeInternal(), aContentType);
return NS_OK; return NS_OK;
} }
@ -2444,11 +2446,11 @@ nsDocument::GetContentType(nsAString& aContentType)
void void
nsDocument::SetContentType(const nsAString& aContentType) nsDocument::SetContentType(const nsAString& aContentType)
{ {
NS_ASSERTION(mContentType.IsEmpty() || NS_ASSERTION(GetContentTypeInternal().IsEmpty() ||
mContentType.Equals(NS_ConvertUTF16toUTF8(aContentType)), GetContentTypeInternal().Equals(NS_ConvertUTF16toUTF8(aContentType)),
"Do you really want to change the content-type?"); "Do you really want to change the content-type?");
CopyUTF16toUTF8(aContentType, mContentType); SetContentTypeInternal(NS_ConvertUTF16toUTF8(aContentType));
} }
/* Return true if the document is in the focused top-level window, and is an /* Return true if the document is in the focused top-level window, and is an
@ -7305,7 +7307,7 @@ nsDocument::CloneDocHelper(nsDocument* clone) const
clone->mCompatMode = mCompatMode; clone->mCompatMode = mCompatMode;
clone->mBidiOptions = mBidiOptions; clone->mBidiOptions = mBidiOptions;
clone->mContentLanguage = mContentLanguage; clone->mContentLanguage = mContentLanguage;
clone->mContentType = mContentType; clone->SetContentTypeInternal(GetContentTypeInternal());
clone->mSecurityInfo = mSecurityInfo; clone->mSecurityInfo = mSecurityInfo;
// State from nsDocument // State from nsDocument

View File

@ -81,6 +81,7 @@
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsStringBuffer.h"
nsresult NS_NewDomSelection(nsISelection **aDomSelection); nsresult NS_NewDomSelection(nsISelection **aDomSelection);
@ -95,8 +96,8 @@ public:
nsDocumentEncoder(); nsDocumentEncoder();
virtual ~nsDocumentEncoder(); virtual ~nsDocumentEncoder();
NS_DECL_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsDocumentEncoder)
NS_DECL_NSIDOCUMENTENCODER NS_DECL_NSIDOCUMENTENCODER
protected: protected:
@ -175,17 +176,36 @@ protected:
PRPackedBool mHaltRangeHint; PRPackedBool mHaltRangeHint;
PRPackedBool mIsCopying; // Set to PR_TRUE only while copying PRPackedBool mIsCopying; // Set to PR_TRUE only while copying
PRPackedBool mNodeIsContainer; PRPackedBool mNodeIsContainer;
nsStringBuffer* mCachedBuffer;
}; };
NS_IMPL_ADDREF(nsDocumentEncoder) NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocumentEncoder)
NS_IMPL_RELEASE(nsDocumentEncoder)
NS_INTERFACE_MAP_BEGIN(nsDocumentEncoder) NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocumentEncoder)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDocumentEncoder)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocumentEncoder)
NS_INTERFACE_MAP_ENTRY(nsIDocumentEncoder) NS_INTERFACE_MAP_ENTRY(nsIDocumentEncoder)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
nsDocumentEncoder::nsDocumentEncoder() NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocumentEncoder)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSelection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRange)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCommonParent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocumentEncoder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSelection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRange)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCommonParent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
nsDocumentEncoder::nsDocumentEncoder() : mCachedBuffer(nsnull)
{ {
Initialize(); Initialize();
mMimeType.AssignLiteral("text/plain"); mMimeType.AssignLiteral("text/plain");
@ -202,10 +222,14 @@ void nsDocumentEncoder::Initialize()
mEndRootIndex = 0; mEndRootIndex = 0;
mHaltRangeHint = PR_FALSE; mHaltRangeHint = PR_FALSE;
mNodeIsContainer = PR_FALSE; mNodeIsContainer = PR_FALSE;
mSerializer = nsnull;
} }
nsDocumentEncoder::~nsDocumentEncoder() nsDocumentEncoder::~nsDocumentEncoder()
{ {
if (mCachedBuffer) {
mCachedBuffer->Release();
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -216,10 +240,23 @@ nsDocumentEncoder::Init(nsIDOMDocument* aDocument,
if (!aDocument) if (!aDocument)
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDocument);
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
return NativeInit(doc, aMimeType, aFlags);
}
NS_IMETHODIMP
nsDocumentEncoder::NativeInit(nsIDocument* aDocument,
const nsAString& aMimeType,
PRUint32 aFlags)
{
if (!aDocument)
return NS_ERROR_INVALID_ARG;
Initialize(); Initialize();
mDocument = do_QueryInterface(aDocument); mDocument = aDocument;
NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE);
mMimeType = aMimeType; mMimeType = aMimeType;
@ -266,6 +303,14 @@ nsDocumentEncoder::SetContainerNode(nsIDOMNode *aContainer)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsDocumentEncoder::SetNativeContainerNode(nsINode* aContainer)
{
mNodeIsContainer = PR_TRUE;
mNode = aContainer;
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsDocumentEncoder::SetCharset(const nsACString& aCharset) nsDocumentEncoder::SetCharset(const nsACString& aCharset)
{ {
@ -928,11 +973,26 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
aOutputString.Truncate(); aOutputString.Truncate();
nsCAutoString progId(NS_CONTENTSERIALIZER_CONTRACTID_PREFIX); nsString output;
AppendUTF16toUTF8(mMimeType, progId); static const size_t bufferSize = 2048;
if (!mCachedBuffer) {
mCachedBuffer = nsStringBuffer::Alloc(bufferSize);
}
NS_ASSERTION(!mCachedBuffer->IsReadonly(),
"DocumentEncoder shouldn't keep reference to non-readonly buffer!");
static_cast<PRUnichar*>(mCachedBuffer->Data())[0] = PRUnichar(0);
mCachedBuffer->ToString(0, output, PR_TRUE);
// output owns the buffer now!
mCachedBuffer = nsnull;
mSerializer = do_CreateInstance(progId.get()); if (!mSerializer) {
NS_ENSURE_TRUE(mSerializer, NS_ERROR_NOT_IMPLEMENTED); nsCAutoString progId(NS_CONTENTSERIALIZER_CONTRACTID_PREFIX);
AppendUTF16toUTF8(mMimeType, progId);
mSerializer = do_CreateInstance(progId.get());
NS_ENSURE_TRUE(mSerializer, NS_ERROR_NOT_IMPLEMENTED);
}
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -966,47 +1026,59 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
if (node != prevNode) { if (node != prevNode) {
if (prevNode) { if (prevNode) {
nsCOMPtr<nsINode> p = do_QueryInterface(prevNode); nsCOMPtr<nsINode> p = do_QueryInterface(prevNode);
rv = SerializeNodeEnd(p, aOutputString); rv = SerializeNodeEnd(p, output);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
prevNode = nsnull; prevNode = nsnull;
} }
nsCOMPtr<nsIContent> content = do_QueryInterface(node); nsCOMPtr<nsIContent> content = do_QueryInterface(node);
if (content && content->Tag() == nsGkAtoms::tr) { if (content && content->Tag() == nsGkAtoms::tr) {
nsCOMPtr<nsINode> n = do_QueryInterface(node); nsCOMPtr<nsINode> n = do_QueryInterface(node);
rv = SerializeNodeStart(n, 0, -1, aOutputString); rv = SerializeNodeStart(n, 0, -1, output);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
prevNode = node; prevNode = node;
} }
} }
nsCOMPtr<nsIRange> r = do_QueryInterface(range); nsCOMPtr<nsIRange> r = do_QueryInterface(range);
rv = SerializeRangeToString(r, aOutputString); rv = SerializeRangeToString(r, output);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (prevNode) { if (prevNode) {
nsCOMPtr<nsINode> p = do_QueryInterface(prevNode); nsCOMPtr<nsINode> p = do_QueryInterface(prevNode);
rv = SerializeNodeEnd(p, aOutputString); rv = SerializeNodeEnd(p, output);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
mSelection = nsnull; mSelection = nsnull;
} else if (mRange) { } else if (mRange) {
rv = SerializeRangeToString(mRange, aOutputString); rv = SerializeRangeToString(mRange, output);
mRange = nsnull; mRange = nsnull;
} else if (mNode) { } else if (mNode) {
rv = SerializeToStringRecursive(mNode, aOutputString, mNodeIsContainer); rv = SerializeToStringRecursive(mNode, output, mNodeIsContainer);
mNode = nsnull; mNode = nsnull;
} else { } else {
rv = mSerializer->AppendDocumentStart(mDocument, aOutputString); rv = mSerializer->AppendDocumentStart(mDocument, output);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
rv = SerializeToStringRecursive(mDocument, aOutputString, PR_FALSE); rv = SerializeToStringRecursive(mDocument, output, PR_FALSE);
} }
} }
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = mSerializer->Flush(aOutputString); rv = mSerializer->Flush(output);
if (NS_SUCCEEDED(rv)) {
aOutputString.Append(output.get(), output.Length());
}
mCachedBuffer = nsStringBuffer::FromString(output);
// Try to cache the buffer.
if (mCachedBuffer && mCachedBuffer->StorageSize() == bufferSize &&
!mCachedBuffer->IsReadonly()) {
mCachedBuffer->AddRef();
} else {
mCachedBuffer = nsnull;
}
return rv; return rv;
} }

View File

@ -101,6 +101,8 @@ nsXHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
const char* aCharSet, PRBool aIsCopying, const char* aCharSet, PRBool aIsCopying,
PRBool aRewriteEncodingDeclaration) PRBool aRewriteEncodingDeclaration)
{ {
mInBody = 0;
// The previous version of the HTML serializer did implicit wrapping // The previous version of the HTML serializer did implicit wrapping
// when there is no flags, so we keep wrapping in order to keep // when there is no flags, so we keep wrapping in order to keep
// compatibility with the existing calling code // compatibility with the existing calling code

View File

@ -111,6 +111,15 @@ nsXMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn,
const char* aCharSet, PRBool aIsCopying, const char* aCharSet, PRBool aIsCopying,
PRBool aRewriteEncodingDeclaration) PRBool aRewriteEncodingDeclaration)
{ {
mPrefixIndex = 0;
mColPos = 0;
mIndentOverflow = 0;
mIsIndentationAddedOnCurrentLine = PR_FALSE;
mInAttribute = PR_FALSE;
mAddNewlineForRootNode = PR_FALSE;
mAddSpace = PR_FALSE;
mMayIgnoreLineBreakSequence = PR_FALSE;
mCharset = aCharSet; mCharset = aCharSet;
mFlags = aFlags; mFlags = aFlags;

View File

@ -655,13 +655,11 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML)
{ {
aInnerHTML.Truncate(); aInnerHTML.Truncate();
nsCOMPtr<nsIDocument> doc = GetOwnerDoc(); nsIDocument* doc = GetOwnerDoc();
if (!doc) { if (!doc) {
return NS_OK; // We rely on the document for doing HTML conversion return NS_OK; // We rely on the document for doing HTML conversion
} }
nsCOMPtr<nsIDOMNode> thisNode(do_QueryInterface(static_cast<nsIContent *>
(this)));
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsAutoString contentType; nsAutoString contentType;
@ -670,13 +668,15 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML)
} else { } else {
doc->GetContentType(contentType); doc->GetContentType(contentType);
} }
nsCOMPtr<nsIDocumentEncoder> docEncoder; nsCOMPtr<nsIDocumentEncoder> docEncoder = doc->GetCachedEncoder();
docEncoder = if (!docEncoder) {
do_CreateInstance(PromiseFlatCString( docEncoder =
do_CreateInstance(PromiseFlatCString(
nsDependentCString(NS_DOC_ENCODER_CONTRACTID_BASE) + nsDependentCString(NS_DOC_ENCODER_CONTRACTID_BASE) +
NS_ConvertUTF16toUTF8(contentType) NS_ConvertUTF16toUTF8(contentType)
).get()); ).get());
}
if (!(docEncoder || doc->IsHTML())) { if (!(docEncoder || doc->IsHTML())) {
// This could be some type for which we create a synthetic document. Try // This could be some type for which we create a synthetic document. Try
// again as XML // again as XML
@ -686,17 +686,19 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML)
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(doc); rv = docEncoder->NativeInit(doc, contentType,
rv = docEncoder->Init(domDoc, contentType, nsIDocumentEncoder::OutputEncodeBasicEntities |
nsIDocumentEncoder::OutputEncodeBasicEntities | // Output DOM-standard newlines
// Output DOM-standard newlines nsIDocumentEncoder::OutputLFLineBreak |
nsIDocumentEncoder::OutputLFLineBreak | // Don't do linebreaking that's not present in
// Don't do linebreaking that's not present in the source // the source
nsIDocumentEncoder::OutputRaw); nsIDocumentEncoder::OutputRaw);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
docEncoder->SetContainerNode(thisNode); docEncoder->SetNativeContainerNode(this);
return docEncoder->EncodeToString(aInnerHTML); rv = docEncoder->EncodeToString(aInnerHTML);
doc->SetCachedEncoder(docEncoder);
return rv;
} }
nsresult nsresult

View File

@ -342,7 +342,7 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
// Make the content type default to "text/html", we are a HTML // Make the content type default to "text/html", we are a HTML
// document, after all. Once we start getting data, this may be // document, after all. Once we start getting data, this may be
// changed. // changed.
mContentType = "text/html"; SetContentTypeInternal(nsDependentCString("text/html"));
} }
nsStyleSet::sheetType nsStyleSet::sheetType
@ -2035,7 +2035,7 @@ nsHTMLDocument::OpenCommon(const nsACString& aContentType, PRBool aReplace)
} }
// This will be propagated to the parser when someone actually calls write() // This will be propagated to the parser when someone actually calls write()
mContentType = aContentType; SetContentTypeInternal(aContentType);
mWriteState = eDocumentOpened; mWriteState = eDocumentOpened;
@ -2134,7 +2134,7 @@ nsHTMLDocument::Close()
++mWriteLevel; ++mWriteLevel;
rv = mParser->Parse(EmptyString(), mParser->GetRootContextKey(), rv = mParser->Parse(EmptyString(), mParser->GetRootContextKey(),
mContentType, PR_TRUE); GetContentTypeInternal(), PR_TRUE);
--mWriteLevel; --mWriteLevel;
// XXX Make sure that all the document.written content is // XXX Make sure that all the document.written content is
@ -2234,11 +2234,11 @@ nsHTMLDocument::WriteCommon(const nsAString& aText,
// why pay that price when we don't need to? // why pay that price when we don't need to?
if (aNewlineTerminate) { if (aNewlineTerminate) {
rv = mParser->Parse(aText + new_line, rv = mParser->Parse(aText + new_line,
key, mContentType, key, GetContentTypeInternal(),
(mWriteState == eNotWriting || (mWriteLevel > 1))); (mWriteState == eNotWriting || (mWriteLevel > 1)));
} else { } else {
rv = mParser->Parse(aText, rv = mParser->Parse(aText,
key, mContentType, key, GetContentTypeInternal(),
(mWriteState == eNotWriting || (mWriteLevel > 1))); (mWriteState == eNotWriting || (mWriteLevel > 1)));
} }

View File

@ -165,8 +165,10 @@ class nsStringBuffer
* however, string length is always measured in storage units * however, string length is always measured in storage units
* (2-byte units for wide strings). * (2-byte units for wide strings).
*/ */
NS_COM void ToString(PRUint32 len, nsAString &str); NS_COM void ToString(PRUint32 len, nsAString &str,
NS_COM void ToString(PRUint32 len, nsACString &str); PRBool aMoveOwnership = PR_FALSE);
NS_COM void ToString(PRUint32 len, nsACString &str,
PRBool aMoveOwnership = PR_FALSE);
}; };
#endif /* !defined(nsStringBuffer_h__ */ #endif /* !defined(nsStringBuffer_h__ */

View File

@ -264,7 +264,8 @@ nsStringBuffer::FromString(const nsACString& str)
} }
void void
nsStringBuffer::ToString(PRUint32 len, nsAString &str) nsStringBuffer::ToString(PRUint32 len, nsAString &str,
PRBool aMoveOwnership)
{ {
PRUnichar* data = static_cast<PRUnichar*>(Data()); PRUnichar* data = static_cast<PRUnichar*>(Data());
@ -275,12 +276,15 @@ nsStringBuffer::ToString(PRUint32 len, nsAString &str)
PRUint32 flags = accessor->flags(); PRUint32 flags = accessor->flags();
flags = (flags & 0xFFFF0000) | nsSubstring::F_SHARED | nsSubstring::F_TERMINATED; flags = (flags & 0xFFFF0000) | nsSubstring::F_SHARED | nsSubstring::F_TERMINATED;
AddRef(); if (!aMoveOwnership) {
AddRef();
}
accessor->set(data, len, flags); accessor->set(data, len, flags);
} }
void void
nsStringBuffer::ToString(PRUint32 len, nsACString &str) nsStringBuffer::ToString(PRUint32 len, nsACString &str,
PRBool aMoveOwnership)
{ {
char* data = static_cast<char*>(Data()); char* data = static_cast<char*>(Data());
@ -291,7 +295,9 @@ nsStringBuffer::ToString(PRUint32 len, nsACString &str)
PRUint32 flags = accessor->flags(); PRUint32 flags = accessor->flags();
flags = (flags & 0xFFFF0000) | nsCSubstring::F_SHARED | nsCSubstring::F_TERMINATED; flags = (flags & 0xFFFF0000) | nsCSubstring::F_SHARED | nsCSubstring::F_TERMINATED;
AddRef(); if (!aMoveOwnership) {
AddRef();
}
accessor->set(data, len, flags); accessor->set(data, len, flags);
} }