diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index a60f69fa6062..157e9892f969 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -63,6 +63,7 @@ #include "nsSMILAnimationController.h" #endif // MOZ_SMIL #include "nsIScriptGlobalObject.h" +#include "nsIDocumentEncoder.h" class nsIContent; class nsPresContext; @@ -116,10 +117,9 @@ class Element; } // namespace mozilla -// fbcd570b-dbfa-479b-9bd0-02312129c044 #define NS_IDOCUMENT_IID \ -{ 0xfbcd570b, 0xdbfa, 0x479b, \ - { 0x9b, 0xd0, 0x02, 0x31, 0x21, 0x29, 0xc0, 0x44 } } +{ 0x1d8bd3d4, 0x6f6d, 0x49fe, \ + { 0xaf, 0xda, 0xc9, 0x4a, 0xef, 0x8f, 0xcf, 0x1f } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -1115,6 +1115,16 @@ public: // Do nothing. } + already_AddRefed GetCachedEncoder() + { + return mCachedEncoder.forget(); + } + + void SetCachedEncoder(nsIDocumentEncoder* aEncoder) + { + mCachedEncoder = aEncoder; + } + // In case of failure, the document really can't initialize the frame loader. virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) = 0; // In case of failure, the caller must handle the error, for example by @@ -1422,6 +1432,17 @@ protected: return GetRootElement(); } + void SetContentTypeInternal(const nsACString& aType) + { + mCachedEncoder = nsnull; + mContentType = aType; + } + + nsCString GetContentTypeInternal() const + { + return mContentType; + } + nsCOMPtr mDocumentURI; nsCOMPtr mDocumentBaseURI; @@ -1530,7 +1551,9 @@ protected: PRUint32 mBidiOptions; nsCString mContentLanguage; +private: nsCString mContentType; +protected: // The document's security info nsCOMPtr mSecurityInfo; @@ -1560,6 +1583,8 @@ protected: // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow, // updated on every set of mSecriptGlobalObject. nsPIDOMWindow *mWindow; + + nsCOMPtr mCachedEncoder; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID) diff --git a/content/base/public/nsIDocumentEncoder.idl b/content/base/public/nsIDocumentEncoder.idl index d83a2eabec8a..13cadc20e924 100644 --- a/content/base/public/nsIDocumentEncoder.idl +++ b/content/base/public/nsIDocumentEncoder.idl @@ -44,6 +44,13 @@ interface nsISelection; interface nsIDOMNode; interface nsIOutputStream; +%{ C++ +class nsINode; +class nsIDocument; +%} +[ptr] native nsINodePtr(nsINode); +[ptr] native nsIDocumentPtr(nsIDocument); + [scriptable, uuid(c0da5b87-0ba7-4d7c-8cb3-fcb02af4253d)] interface nsIDocumentEncoderNodeFixup : nsISupports { @@ -61,7 +68,7 @@ interface nsIDocumentEncoderNodeFixup : nsISupports 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 { // Output methods flag bits. There are a frightening number of these, @@ -238,6 +245,9 @@ interface nsIDocumentEncoder : nsISupports void init(in nsIDOMDocument aDocument, in AString aMimeType, 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 @@ -270,6 +280,7 @@ interface nsIDocumentEncoder : nsISupports * @param aContainer The node which child nodes will be encoded. */ void setContainerNode(in nsIDOMNode aContainer); + [noscript] void setNativeContainerNode(in nsINodePtr aContainer); /** * Documents typically have an intrinsic character set, diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 664eca314cd6..08ff0e469b6b 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1393,7 +1393,7 @@ nsDOMImplementation::Init(nsIURI* aDocumentURI, nsIURI* aBaseURI, nsDocument::nsDocument(const char* aContentType) : nsIDocument() { - mContentType = aContentType; + SetContentTypeInternal(nsDependentCString(aContentType)); #ifdef PR_LOGGING 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(mDOMImplementation) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOriginalDocument) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedEncoder) // Traverse all our nsCOMArrays. 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(mDOMImplementation) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOriginalDocument) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedEncoder) NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA @@ -1947,7 +1949,7 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, mLastModified.Truncate(); // XXXbz I guess we're assuming that the caller will either pass in // a channel with a useful type or call SetContentType? - mContentType.Truncate(); + SetContentTypeInternal(EmptyCString()); mContentLanguage.Truncate(); mBaseTarget.Truncate(); mReferrer.Truncate(); @@ -2155,7 +2157,7 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, contentType.EndReading(end); semicolon = start; FindCharInReadable(';', semicolon, end); - mContentType = Substring(start, semicolon); + SetContentTypeInternal(Substring(start, semicolon)); } RetrieveRelevantHeaders(aChannel); @@ -2436,7 +2438,7 @@ nsDocument::SetApplicationCache(nsIApplicationCache *aApplicationCache) NS_IMETHODIMP nsDocument::GetContentType(nsAString& aContentType) { - CopyUTF8toUTF16(mContentType, aContentType); + CopyUTF8toUTF16(GetContentTypeInternal(), aContentType); return NS_OK; } @@ -2444,11 +2446,11 @@ nsDocument::GetContentType(nsAString& aContentType) void nsDocument::SetContentType(const nsAString& aContentType) { - NS_ASSERTION(mContentType.IsEmpty() || - mContentType.Equals(NS_ConvertUTF16toUTF8(aContentType)), + NS_ASSERTION(GetContentTypeInternal().IsEmpty() || + GetContentTypeInternal().Equals(NS_ConvertUTF16toUTF8(aContentType)), "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 @@ -7305,7 +7307,7 @@ nsDocument::CloneDocHelper(nsDocument* clone) const clone->mCompatMode = mCompatMode; clone->mBidiOptions = mBidiOptions; clone->mContentLanguage = mContentLanguage; - clone->mContentType = mContentType; + clone->SetContentTypeInternal(GetContentTypeInternal()); clone->mSecurityInfo = mSecurityInfo; // State from nsDocument diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index f7be93c89d6d..e966415bad9c 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -81,6 +81,7 @@ #include "nsReadableUtils.h" #include "nsTArray.h" #include "nsIFrame.h" +#include "nsStringBuffer.h" nsresult NS_NewDomSelection(nsISelection **aDomSelection); @@ -95,8 +96,8 @@ public: nsDocumentEncoder(); virtual ~nsDocumentEncoder(); - NS_DECL_ISUPPORTS - + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(nsDocumentEncoder) NS_DECL_NSIDOCUMENTENCODER protected: @@ -175,17 +176,36 @@ protected: PRPackedBool mHaltRangeHint; PRPackedBool mIsCopying; // Set to PR_TRUE only while copying PRPackedBool mNodeIsContainer; + nsStringBuffer* mCachedBuffer; }; -NS_IMPL_ADDREF(nsDocumentEncoder) -NS_IMPL_RELEASE(nsDocumentEncoder) +NS_IMPL_CYCLE_COLLECTION_CLASS(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(nsISupports) 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(); mMimeType.AssignLiteral("text/plain"); @@ -202,10 +222,14 @@ void nsDocumentEncoder::Initialize() mEndRootIndex = 0; mHaltRangeHint = PR_FALSE; mNodeIsContainer = PR_FALSE; + mSerializer = nsnull; } nsDocumentEncoder::~nsDocumentEncoder() { + if (mCachedBuffer) { + mCachedBuffer->Release(); + } } NS_IMETHODIMP @@ -216,10 +240,23 @@ nsDocumentEncoder::Init(nsIDOMDocument* aDocument, if (!aDocument) return NS_ERROR_INVALID_ARG; + nsCOMPtr 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(); - mDocument = do_QueryInterface(aDocument); - NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); + mDocument = aDocument; mMimeType = aMimeType; @@ -266,6 +303,14 @@ nsDocumentEncoder::SetContainerNode(nsIDOMNode *aContainer) return NS_OK; } +NS_IMETHODIMP +nsDocumentEncoder::SetNativeContainerNode(nsINode* aContainer) +{ + mNodeIsContainer = PR_TRUE; + mNode = aContainer; + return NS_OK; +} + NS_IMETHODIMP nsDocumentEncoder::SetCharset(const nsACString& aCharset) { @@ -928,11 +973,26 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString) aOutputString.Truncate(); - nsCAutoString progId(NS_CONTENTSERIALIZER_CONTRACTID_PREFIX); - AppendUTF16toUTF8(mMimeType, progId); + nsString output; + 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(mCachedBuffer->Data())[0] = PRUnichar(0); + mCachedBuffer->ToString(0, output, PR_TRUE); + // output owns the buffer now! + mCachedBuffer = nsnull; + - mSerializer = do_CreateInstance(progId.get()); - NS_ENSURE_TRUE(mSerializer, NS_ERROR_NOT_IMPLEMENTED); + if (!mSerializer) { + 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; @@ -966,47 +1026,59 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString) if (node != prevNode) { if (prevNode) { nsCOMPtr p = do_QueryInterface(prevNode); - rv = SerializeNodeEnd(p, aOutputString); + rv = SerializeNodeEnd(p, output); NS_ENSURE_SUCCESS(rv, rv); prevNode = nsnull; } nsCOMPtr content = do_QueryInterface(node); if (content && content->Tag() == nsGkAtoms::tr) { nsCOMPtr n = do_QueryInterface(node); - rv = SerializeNodeStart(n, 0, -1, aOutputString); + rv = SerializeNodeStart(n, 0, -1, output); NS_ENSURE_SUCCESS(rv, rv); prevNode = node; } } nsCOMPtr r = do_QueryInterface(range); - rv = SerializeRangeToString(r, aOutputString); + rv = SerializeRangeToString(r, output); NS_ENSURE_SUCCESS(rv, rv); } if (prevNode) { nsCOMPtr p = do_QueryInterface(prevNode); - rv = SerializeNodeEnd(p, aOutputString); + rv = SerializeNodeEnd(p, output); NS_ENSURE_SUCCESS(rv, rv); } mSelection = nsnull; } else if (mRange) { - rv = SerializeRangeToString(mRange, aOutputString); + rv = SerializeRangeToString(mRange, output); mRange = nsnull; } else if (mNode) { - rv = SerializeToStringRecursive(mNode, aOutputString, mNodeIsContainer); + rv = SerializeToStringRecursive(mNode, output, mNodeIsContainer); mNode = nsnull; } else { - rv = mSerializer->AppendDocumentStart(mDocument, aOutputString); + rv = mSerializer->AppendDocumentStart(mDocument, output); if (NS_SUCCEEDED(rv)) { - rv = SerializeToStringRecursive(mDocument, aOutputString, PR_FALSE); + rv = SerializeToStringRecursive(mDocument, output, PR_FALSE); } } 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; } diff --git a/content/base/src/nsXHTMLContentSerializer.cpp b/content/base/src/nsXHTMLContentSerializer.cpp index 21d603fa33de..12bf1cc69b20 100644 --- a/content/base/src/nsXHTMLContentSerializer.cpp +++ b/content/base/src/nsXHTMLContentSerializer.cpp @@ -101,6 +101,8 @@ nsXHTMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn, const char* aCharSet, PRBool aIsCopying, PRBool aRewriteEncodingDeclaration) { + mInBody = 0; + // The previous version of the HTML serializer did implicit wrapping // when there is no flags, so we keep wrapping in order to keep // compatibility with the existing calling code diff --git a/content/base/src/nsXMLContentSerializer.cpp b/content/base/src/nsXMLContentSerializer.cpp index f02958538995..aa65d0582501 100644 --- a/content/base/src/nsXMLContentSerializer.cpp +++ b/content/base/src/nsXMLContentSerializer.cpp @@ -111,6 +111,15 @@ nsXMLContentSerializer::Init(PRUint32 aFlags, PRUint32 aWrapColumn, const char* aCharSet, PRBool aIsCopying, 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; mFlags = aFlags; diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 01b13d991018..ca565fc6dadb 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -655,13 +655,11 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) { aInnerHTML.Truncate(); - nsCOMPtr doc = GetOwnerDoc(); + nsIDocument* doc = GetOwnerDoc(); if (!doc) { return NS_OK; // We rely on the document for doing HTML conversion } - nsCOMPtr thisNode(do_QueryInterface(static_cast - (this))); nsresult rv = NS_OK; nsAutoString contentType; @@ -670,13 +668,15 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) } else { doc->GetContentType(contentType); } - - nsCOMPtr docEncoder; - docEncoder = - do_CreateInstance(PromiseFlatCString( + + nsCOMPtr docEncoder = doc->GetCachedEncoder(); + if (!docEncoder) { + docEncoder = + do_CreateInstance(PromiseFlatCString( nsDependentCString(NS_DOC_ENCODER_CONTRACTID_BASE) + NS_ConvertUTF16toUTF8(contentType) ).get()); + } if (!(docEncoder || doc->IsHTML())) { // This could be some type for which we create a synthetic document. Try // again as XML @@ -686,17 +686,19 @@ nsGenericHTMLElement::GetInnerHTML(nsAString& aInnerHTML) NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE); - nsCOMPtr domDoc = do_QueryInterface(doc); - rv = docEncoder->Init(domDoc, contentType, - nsIDocumentEncoder::OutputEncodeBasicEntities | - // Output DOM-standard newlines - nsIDocumentEncoder::OutputLFLineBreak | - // Don't do linebreaking that's not present in the source - nsIDocumentEncoder::OutputRaw); + rv = docEncoder->NativeInit(doc, contentType, + nsIDocumentEncoder::OutputEncodeBasicEntities | + // Output DOM-standard newlines + nsIDocumentEncoder::OutputLFLineBreak | + // Don't do linebreaking that's not present in + // the source + nsIDocumentEncoder::OutputRaw); NS_ENSURE_SUCCESS(rv, rv); - docEncoder->SetContainerNode(thisNode); - return docEncoder->EncodeToString(aInnerHTML); + docEncoder->SetNativeContainerNode(this); + rv = docEncoder->EncodeToString(aInnerHTML); + doc->SetCachedEncoder(docEncoder); + return rv; } nsresult diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index d2a363f4d845..2026ce4c5663 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -342,7 +342,7 @@ nsHTMLDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, // Make the content type default to "text/html", we are a HTML // document, after all. Once we start getting data, this may be // changed. - mContentType = "text/html"; + SetContentTypeInternal(nsDependentCString("text/html")); } 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() - mContentType = aContentType; + SetContentTypeInternal(aContentType); mWriteState = eDocumentOpened; @@ -2134,7 +2134,7 @@ nsHTMLDocument::Close() ++mWriteLevel; rv = mParser->Parse(EmptyString(), mParser->GetRootContextKey(), - mContentType, PR_TRUE); + GetContentTypeInternal(), PR_TRUE); --mWriteLevel; // 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? if (aNewlineTerminate) { rv = mParser->Parse(aText + new_line, - key, mContentType, + key, GetContentTypeInternal(), (mWriteState == eNotWriting || (mWriteLevel > 1))); } else { rv = mParser->Parse(aText, - key, mContentType, + key, GetContentTypeInternal(), (mWriteState == eNotWriting || (mWriteLevel > 1))); } diff --git a/xpcom/string/public/nsStringBuffer.h b/xpcom/string/public/nsStringBuffer.h index 6ea57561c88b..c88a018cec76 100644 --- a/xpcom/string/public/nsStringBuffer.h +++ b/xpcom/string/public/nsStringBuffer.h @@ -165,8 +165,10 @@ class nsStringBuffer * however, string length is always measured in storage units * (2-byte units for wide strings). */ - NS_COM void ToString(PRUint32 len, nsAString &str); - NS_COM void ToString(PRUint32 len, nsACString &str); + NS_COM void ToString(PRUint32 len, nsAString &str, + PRBool aMoveOwnership = PR_FALSE); + NS_COM void ToString(PRUint32 len, nsACString &str, + PRBool aMoveOwnership = PR_FALSE); }; #endif /* !defined(nsStringBuffer_h__ */ diff --git a/xpcom/string/src/nsSubstring.cpp b/xpcom/string/src/nsSubstring.cpp index f4537c7526cd..3b6d09203e30 100644 --- a/xpcom/string/src/nsSubstring.cpp +++ b/xpcom/string/src/nsSubstring.cpp @@ -264,7 +264,8 @@ nsStringBuffer::FromString(const nsACString& str) } void -nsStringBuffer::ToString(PRUint32 len, nsAString &str) +nsStringBuffer::ToString(PRUint32 len, nsAString &str, + PRBool aMoveOwnership) { PRUnichar* data = static_cast(Data()); @@ -275,12 +276,15 @@ nsStringBuffer::ToString(PRUint32 len, nsAString &str) PRUint32 flags = accessor->flags(); flags = (flags & 0xFFFF0000) | nsSubstring::F_SHARED | nsSubstring::F_TERMINATED; - AddRef(); + if (!aMoveOwnership) { + AddRef(); + } accessor->set(data, len, flags); } void -nsStringBuffer::ToString(PRUint32 len, nsACString &str) +nsStringBuffer::ToString(PRUint32 len, nsACString &str, + PRBool aMoveOwnership) { char* data = static_cast(Data()); @@ -291,7 +295,9 @@ nsStringBuffer::ToString(PRUint32 len, nsACString &str) PRUint32 flags = accessor->flags(); flags = (flags & 0xFFFF0000) | nsCSubstring::F_SHARED | nsCSubstring::F_TERMINATED; - AddRef(); + if (!aMoveOwnership) { + AddRef(); + } accessor->set(data, len, flags); }