From 7c5a0db237c7a43136ee3cdc6cfb0663778d9e2c Mon Sep 17 00:00:00 2001 From: win7-7 Date: Fri, 5 Jul 2019 21:58:21 +0300 Subject: Introduce a new non-heap-allocated type for holding nsStringBuffer* in the HTML parser. An innerHTML setter profile shows about 10% of the time being spent under nsHtml5HtmlAttributes::clear, mostly deleting nsStrings. --- parser/html/moz.build | 2 + parser/html/nsHtml5ArrayCopy.h | 7 +- parser/html/nsHtml5AttributeName.cpp | 2 +- parser/html/nsHtml5AttributeName.h | 2 +- parser/html/nsHtml5ElementName.cpp | 2 +- parser/html/nsHtml5ElementName.h | 2 +- parser/html/nsHtml5Highlighter.cpp | 16 +- parser/html/nsHtml5Highlighter.h | 6 +- parser/html/nsHtml5HtmlAttributes.cpp | 27 +-- parser/html/nsHtml5HtmlAttributes.h | 12 +- parser/html/nsHtml5MetaScanner.cpp | 15 +- parser/html/nsHtml5MetaScanner.h | 8 +- parser/html/nsHtml5MetaScannerCppSupplement.h | 6 +- parser/html/nsHtml5PlainTextUtils.cpp | 15 +- parser/html/nsHtml5Portability.cpp | 99 ++++------- parser/html/nsHtml5Portability.h | 29 ++-- parser/html/nsHtml5SpeculativeLoad.h | 106 ++++++------ parser/html/nsHtml5StackNode.cpp | 2 +- parser/html/nsHtml5StackNode.h | 2 +- parser/html/nsHtml5StateSnapshot.cpp | 2 +- parser/html/nsHtml5StateSnapshot.h | 2 +- parser/html/nsHtml5StreamParser.cpp | 7 +- parser/html/nsHtml5StreamParser.h | 2 +- parser/html/nsHtml5String.cpp | 226 ++++++++++++++++++++++++++ parser/html/nsHtml5String.h | 95 +++++++++++ parser/html/nsHtml5Tokenizer.cpp | 34 ++-- parser/html/nsHtml5Tokenizer.h | 16 +- parser/html/nsHtml5TreeBuilder.cpp | 49 ++++-- parser/html/nsHtml5TreeBuilder.h | 27 ++- parser/html/nsHtml5TreeBuilderCppSupplement.h | 206 +++++++++++------------ parser/html/nsHtml5TreeOperation.cpp | 14 +- parser/html/nsHtml5UTF16Buffer.cpp | 2 +- parser/html/nsHtml5UTF16Buffer.h | 2 +- parser/html/nsHtml5ViewSourceUtils.cpp | 33 ++-- 34 files changed, 719 insertions(+), 358 deletions(-) create mode 100644 parser/html/nsHtml5String.cpp create mode 100644 parser/html/nsHtml5String.h (limited to 'parser') diff --git a/parser/html/moz.build b/parser/html/moz.build index 4a2da8a79..cd6031abe 100644 --- a/parser/html/moz.build +++ b/parser/html/moz.build @@ -39,6 +39,7 @@ EXPORTS += [ 'nsHtml5SpeculativeLoad.h', 'nsHtml5StreamListener.h', 'nsHtml5StreamParser.h', + 'nsHtml5String.h', 'nsHtml5StringParser.h', 'nsHtml5SVGLoadDispatcher.h', 'nsHtml5TreeOperation.h', @@ -78,6 +79,7 @@ UNIFIED_SOURCES += [ 'nsHtml5StateSnapshot.cpp', 'nsHtml5StreamListener.cpp', 'nsHtml5StreamParser.cpp', + 'nsHtml5String.cpp', 'nsHtml5StringParser.cpp', 'nsHtml5SVGLoadDispatcher.cpp', 'nsHtml5Tokenizer.cpp', diff --git a/parser/html/nsHtml5ArrayCopy.h b/parser/html/nsHtml5ArrayCopy.h index 78ed65568..594a801ab 100644 --- a/parser/html/nsHtml5ArrayCopy.h +++ b/parser/html/nsHtml5ArrayCopy.h @@ -51,10 +51,11 @@ class nsHtml5ArrayCopy { memcpy(target, source, size_t(length) * sizeof(int32_t)); } - static inline void - arraycopy(nsString** source, nsString** target, int32_t length) + static inline void arraycopy(nsHtml5String* source, + nsHtml5String* target, + int32_t length) { - memcpy(target, source, size_t(length) * sizeof(nsString*)); + memcpy(target, source, size_t(length) * sizeof(nsHtml5String)); } static inline void diff --git a/parser/html/nsHtml5AttributeName.cpp b/parser/html/nsHtml5AttributeName.cpp index fc7745adc..dc546c111 100644 --- a/parser/html/nsHtml5AttributeName.cpp +++ b/parser/html/nsHtml5AttributeName.cpp @@ -29,7 +29,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5AttributeName.h b/parser/html/nsHtml5AttributeName.h index 748dcf3c9..d0b93341b 100644 --- a/parser/html/nsHtml5AttributeName.h +++ b/parser/html/nsHtml5AttributeName.h @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5ElementName.cpp b/parser/html/nsHtml5ElementName.cpp index 1aa6f11ce..fb523e7ef 100644 --- a/parser/html/nsHtml5ElementName.cpp +++ b/parser/html/nsHtml5ElementName.cpp @@ -29,7 +29,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5ElementName.h b/parser/html/nsHtml5ElementName.h index b4df323a6..b5f0e4b9b 100644 --- a/parser/html/nsHtml5ElementName.h +++ b/parser/html/nsHtml5ElementName.h @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5Highlighter.cpp b/parser/html/nsHtml5Highlighter.cpp index 259803ee1..23cdf7d84 100644 --- a/parser/html/nsHtml5Highlighter.cpp +++ b/parser/html/nsHtml5Highlighter.cpp @@ -91,7 +91,7 @@ nsHtml5Highlighter::Start(const nsAutoString& aTitle) if (length > INT32_MAX) { length = INT32_MAX; } - AppendCharacters(aTitle.get(), 0, (int32_t)length); + AppendCharacters(aTitle.BeginReading(), 0, (int32_t)length); Pop(); // title Push(nsGkAtoms::link, nsHtml5ViewSourceUtils::NewLinkAttributes()); @@ -105,7 +105,7 @@ nsHtml5Highlighter::Start(const nsAutoString& aTitle) Push(nsGkAtoms::body, nsHtml5ViewSourceUtils::NewBodyAttributes()); nsHtml5HtmlAttributes* preAttrs = new nsHtml5HtmlAttributes(0); - nsString* preId = new nsString(NS_LITERAL_STRING("line1")); + nsHtml5String preId = nsHtml5Portability::newStringFromLiteral("line1"); preAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, preId, -1); Push(nsGkAtoms::pre, preAttrs); @@ -618,7 +618,7 @@ nsHtml5Highlighter::FlushOps() void nsHtml5Highlighter::MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName, - nsString* aValue) + nsHtml5String aValue) { if (!(nsHtml5AttributeName::ATTR_HREF == aName || nsHtml5AttributeName::ATTR_SRC == aName || @@ -630,7 +630,7 @@ nsHtml5Highlighter::MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName, nsHtml5AttributeName::ATTR_DEFINITIONURL == aName)) { return; } - AddViewSourceHref(*aValue); + AddViewSourceHref(aValue); } void @@ -717,10 +717,10 @@ nsHtml5Highlighter::AddClass(const char16_t* aClass) } void -nsHtml5Highlighter::AddViewSourceHref(const nsString& aValue) +nsHtml5Highlighter::AddViewSourceHref(nsHtml5String aValue) { char16_t* bufferCopy = new char16_t[aValue.Length() + 1]; - memcpy(bufferCopy, aValue.get(), aValue.Length() * sizeof(char16_t)); + aValue.CopyToBuffer(bufferCopy); bufferCopy[aValue.Length()] = 0; mOpQueue.AppendElement()->Init(eTreeOpAddViewSourceHref, @@ -730,14 +730,14 @@ nsHtml5Highlighter::AddViewSourceHref(const nsString& aValue) } void -nsHtml5Highlighter::AddBase(const nsString& aValue) +nsHtml5Highlighter::AddBase(nsHtml5String aValue) { if(mSeenBase) { return; } mSeenBase = true; char16_t* bufferCopy = new char16_t[aValue.Length() + 1]; - memcpy(bufferCopy, aValue.get(), aValue.Length() * sizeof(char16_t)); + aValue.CopyToBuffer(bufferCopy); bufferCopy[aValue.Length()] = 0; mOpQueue.AppendElement()->Init(eTreeOpAddViewSourceBase, diff --git a/parser/html/nsHtml5Highlighter.h b/parser/html/nsHtml5Highlighter.h index e9474869e..366f11582 100644 --- a/parser/html/nsHtml5Highlighter.h +++ b/parser/html/nsHtml5Highlighter.h @@ -78,7 +78,7 @@ class nsHtml5Highlighter * @param aValue the value of the attribute */ void MaybeLinkifyAttributeValue(nsHtml5AttributeName* aName, - nsString* aValue); + nsHtml5String aValue); /** * Inform the highlighter that the tokenizer successfully completed a @@ -147,7 +147,7 @@ class nsHtml5Highlighter * * @param aValue the base URL to add */ - void AddBase(const nsString& aValue); + void AddBase(nsHtml5String aValue); private: @@ -272,7 +272,7 @@ class nsHtml5Highlighter * * @param aValue the (potentially relative) URL to link to */ - void AddViewSourceHref(const nsString& aValue); + void AddViewSourceHref(nsHtml5String aValue); /** * The state we are transitioning away from. diff --git a/parser/html/nsHtml5HtmlAttributes.cpp b/parser/html/nsHtml5HtmlAttributes.cpp index d515f381d..62b9ae2b2 100644 --- a/parser/html/nsHtml5HtmlAttributes.cpp +++ b/parser/html/nsHtml5HtmlAttributes.cpp @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -58,11 +58,11 @@ nsHtml5HtmlAttributes* nsHtml5HtmlAttributes::EMPTY_ATTRIBUTES = nullptr; nsHtml5HtmlAttributes::nsHtml5HtmlAttributes(int32_t mode) - : mode(mode), - length(0), - names(jArray::newJArray(8)), - values(jArray::newJArray(8)), - lines(jArray::newJArray(8)) + : mode(mode) + , length(0) + , names(jArray::newJArray(8)) + , values(jArray::newJArray(8)) + , lines(jArray::newJArray(8)) { MOZ_COUNT_CTOR(nsHtml5HtmlAttributes); } @@ -85,7 +85,7 @@ nsHtml5HtmlAttributes::getIndex(nsHtml5AttributeName* name) return -1; } -nsString* +nsHtml5String nsHtml5HtmlAttributes::getValue(nsHtml5AttributeName* name) { int32_t index = getIndex(name); @@ -123,7 +123,7 @@ nsHtml5HtmlAttributes::getPrefixNoBoundsCheck(int32_t index) return names[index]->getPrefix(mode); } -nsString* +nsHtml5String nsHtml5HtmlAttributes::getValueNoBoundsCheck(int32_t index) { MOZ_ASSERT(index < length && index >= 0, "Index out of bounds"); @@ -145,14 +145,17 @@ nsHtml5HtmlAttributes::getLineNoBoundsCheck(int32_t index) } void -nsHtml5HtmlAttributes::addAttribute(nsHtml5AttributeName* name, nsString* value, int32_t line) +nsHtml5HtmlAttributes::addAttribute(nsHtml5AttributeName* name, + nsHtml5String value, + int32_t line) { if (names.length == length) { int32_t newLen = length << 1; jArray newNames = jArray::newJArray(newLen); nsHtml5ArrayCopy::arraycopy(names, newNames, names.length); names = newNames; - jArray newValues = jArray::newJArray(newLen); + jArray newValues = + jArray::newJArray(newLen); nsHtml5ArrayCopy::arraycopy(values, newValues, values.length); values = newValues; jArray newLines = jArray::newJArray(newLen); @@ -171,7 +174,7 @@ nsHtml5HtmlAttributes::clear(int32_t m) for (int32_t i = 0; i < length; i++) { names[i]->release(); names[i] = nullptr; - nsHtml5Portability::releaseString(values[i]); + values[i].Release(); values[i] = nullptr; } length = 0; @@ -181,7 +184,7 @@ nsHtml5HtmlAttributes::clear(int32_t m) void nsHtml5HtmlAttributes::releaseValue(int32_t i) { - nsHtml5Portability::releaseString(values[i]); + values[i].Release(); } void diff --git a/parser/html/nsHtml5HtmlAttributes.h b/parser/html/nsHtml5HtmlAttributes.h index c02d0a08c..12149a0b5 100644 --- a/parser/html/nsHtml5HtmlAttributes.h +++ b/parser/html/nsHtml5HtmlAttributes.h @@ -31,7 +31,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -64,21 +64,23 @@ class nsHtml5HtmlAttributes int32_t mode; int32_t length; autoJArray names; - autoJArray values; + autoJArray values; autoJArray lines; public: explicit nsHtml5HtmlAttributes(int32_t mode); ~nsHtml5HtmlAttributes(); int32_t getIndex(nsHtml5AttributeName* name); - nsString* getValue(nsHtml5AttributeName* name); + nsHtml5String getValue(nsHtml5AttributeName* name); int32_t getLength(); nsIAtom* getLocalNameNoBoundsCheck(int32_t index); int32_t getURINoBoundsCheck(int32_t index); nsIAtom* getPrefixNoBoundsCheck(int32_t index); - nsString* getValueNoBoundsCheck(int32_t index); + nsHtml5String getValueNoBoundsCheck(int32_t index); nsHtml5AttributeName* getAttributeNameNoBoundsCheck(int32_t index); int32_t getLineNoBoundsCheck(int32_t index); - void addAttribute(nsHtml5AttributeName* name, nsString* value, int32_t line); + void addAttribute(nsHtml5AttributeName* name, + nsHtml5String value, + int32_t line); void clear(int32_t m); void releaseValue(int32_t i); void clearWithoutReleasingContents(); diff --git a/parser/html/nsHtml5MetaScanner.cpp b/parser/html/nsHtml5MetaScanner.cpp index d39eacd9b..24f17b02b 100644 --- a/parser/html/nsHtml5MetaScanner.cpp +++ b/parser/html/nsHtml5MetaScanner.cpp @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -86,8 +86,8 @@ nsHtml5MetaScanner::nsHtml5MetaScanner(nsHtml5TreeBuilder* tb) nsHtml5MetaScanner::~nsHtml5MetaScanner() { MOZ_COUNT_DTOR(nsHtml5MetaScanner); - nsHtml5Portability::releaseString(content); - nsHtml5Portability::releaseString(charset); + content.Release(); + charset.Release(); } void @@ -771,9 +771,9 @@ bool nsHtml5MetaScanner::handleTag() { bool stop = handleTagInner(); - nsHtml5Portability::releaseString(content); + content.Release(); content = nullptr; - nsHtml5Portability::releaseString(charset); + charset.Release(); charset = nullptr; httpEquivState = NS_HTML5META_SCANNER_HTTP_EQUIV_NOT_SEEN; return stop; @@ -786,12 +786,13 @@ nsHtml5MetaScanner::handleTagInner() return true; } if (!!content && httpEquivState == NS_HTML5META_SCANNER_HTTP_EQUIV_CONTENT_TYPE) { - nsString* extract = nsHtml5TreeBuilder::extractCharsetFromContent(content, treeBuilder); + nsHtml5String extract = + nsHtml5TreeBuilder::extractCharsetFromContent(content, treeBuilder); if (!extract) { return false; } bool success = tryCharset(extract); - nsHtml5Portability::releaseString(extract); + extract.Release(); return success; } return false; diff --git a/parser/html/nsHtml5MetaScanner.h b/parser/html/nsHtml5MetaScanner.h index 4e0ad7647..a4d308147 100644 --- a/parser/html/nsHtml5MetaScanner.h +++ b/parser/html/nsHtml5MetaScanner.h @@ -31,7 +31,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -76,8 +76,8 @@ class nsHtml5MetaScanner private: int32_t strBufLen; autoJArray strBuf; - nsString* content; - nsString* charset; + nsHtml5String content; + nsHtml5String charset; int32_t httpEquivState; nsHtml5TreeBuilder* treeBuilder; public: @@ -100,7 +100,7 @@ class nsHtml5MetaScanner bool handleTag(); bool handleTagInner(); protected: - bool tryCharset(nsString* encoding); + bool tryCharset(nsHtml5String encoding); public: static void initializeStatics(); static void releaseStatics(); diff --git a/parser/html/nsHtml5MetaScannerCppSupplement.h b/parser/html/nsHtml5MetaScannerCppSupplement.h index 5e7033777..9d2496361 100644 --- a/parser/html/nsHtml5MetaScannerCppSupplement.h +++ b/parser/html/nsHtml5MetaScannerCppSupplement.h @@ -19,13 +19,15 @@ nsHtml5MetaScanner::sniff(nsHtml5ByteReadable* bytes, nsACString& charset) } bool -nsHtml5MetaScanner::tryCharset(nsString* charset) +nsHtml5MetaScanner::tryCharset(nsHtml5String charset) { // This code needs to stay in sync with // nsHtml5StreamParser::internalEncodingDeclaration. Unfortunately, the // trickery with member fields here leads to some copy-paste reuse. :-( nsAutoCString label; - CopyUTF16toUTF8(*charset, label); + nsString charset16; // Not Auto, because using it to hold nsStringBuffer* + charset.ToString(charset16); + CopyUTF16toUTF8(charset16, label); nsAutoCString encoding; if (!EncodingUtils::FindEncodingForLabel(label, encoding)) { return false; diff --git a/parser/html/nsHtml5PlainTextUtils.cpp b/parser/html/nsHtml5PlainTextUtils.cpp index 4f0eab81b..0d2933150 100644 --- a/parser/html/nsHtml5PlainTextUtils.cpp +++ b/parser/html/nsHtml5PlainTextUtils.cpp @@ -5,21 +5,24 @@ #include "nsHtml5PlainTextUtils.h" #include "nsHtml5AttributeName.h" +#include "nsHtml5Portability.h" #include "nsIServiceManager.h" #include "nsIStringBundle.h" #include "mozilla/Preferences.h" +#include "nsHtml5String.h" // static nsHtml5HtmlAttributes* nsHtml5PlainTextUtils::NewLinkAttributes() { nsHtml5HtmlAttributes* linkAttrs = new nsHtml5HtmlAttributes(0); - nsString* rel = new nsString(NS_LITERAL_STRING("alternate stylesheet")); + nsHtml5String rel = + nsHtml5Portability::newStringFromLiteral("alternate stylesheet"); linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_REL, rel, -1); - nsString* type = new nsString(NS_LITERAL_STRING("text/css")); + nsHtml5String type = nsHtml5Portability::newStringFromLiteral("text/css"); linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TYPE, type, -1); - nsString* href = new nsString( - NS_LITERAL_STRING("resource://gre-resources/plaintext.css")); + nsHtml5String href = nsHtml5Portability::newStringFromLiteral( + "resource://gre-resources/plaintext.css"); linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1); nsresult rv; @@ -34,7 +37,7 @@ nsHtml5PlainTextUtils::NewLinkAttributes() bundle->GetStringFromName(u"plainText.wordWrap", getter_Copies(title)); } - nsString* titleCopy = new nsString(title); - linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TITLE, titleCopy, -1); + linkAttrs->addAttribute( + nsHtml5AttributeName::ATTR_TITLE, nsHtml5String::FromString(title), -1); return linkAttrs; } diff --git a/parser/html/nsHtml5Portability.cpp b/parser/html/nsHtml5Portability.cpp index 0a7c6f845..5a76b3c56 100644 --- a/parser/html/nsHtml5Portability.cpp +++ b/parser/html/nsHtml5Portability.cpp @@ -16,37 +16,31 @@ nsHtml5Portability::newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_ return interner->GetAtom(nsDependentSubstring(buf, buf + length)); } -nsString* -nsHtml5Portability::newStringFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5TreeBuilder* treeBuilder) +nsHtml5String +nsHtml5Portability::newStringFromBuffer(char16_t* buf, + int32_t offset, + int32_t length, + nsHtml5TreeBuilder* treeBuilder) { - nsString* str = new nsString(); - bool succeeded = str->Append(buf + offset, length, mozilla::fallible); - if (!succeeded) { - str->Assign(char16_t(0xFFFD)); - treeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); - } - return str; + return nsHtml5String::FromBuffer(buf + offset, length, treeBuilder); } -nsString* +nsHtml5String nsHtml5Portability::newEmptyString() { - return new nsString(); + return nsHtml5String::EmptyString(); } -nsString* +nsHtml5String nsHtml5Portability::newStringFromLiteral(const char* literal) { - nsString* str = new nsString(); - str->AssignASCII(literal); - return str; + return nsHtml5String::FromLiteral(literal); } -nsString* -nsHtml5Portability::newStringFromString(nsString* string) { - nsString* newStr = new nsString(); - newStr->Assign(*string); - return newStr; +nsHtml5String +nsHtml5Portability::newStringFromString(nsHtml5String string) +{ + return string.Clone(); } jArray @@ -60,12 +54,14 @@ nsHtml5Portability::newCharArrayFromLocal(nsIAtom* local) return arr; } -jArray -nsHtml5Portability::newCharArrayFromString(nsString* string) +jArray +nsHtml5Portability::newCharArrayFromString(nsHtml5String string) { - int32_t len = string->Length(); + MOZ_RELEASE_ASSERT(string); + uint32_t len = string.Length(); + MOZ_RELEASE_ASSERT(len < INT32_MAX); jArray arr = jArray::newJArray(len); - memcpy(arr, string->BeginReading(), len * sizeof(char16_t)); + string.CopyToBuffer(arr); return arr; } @@ -82,12 +78,6 @@ nsHtml5Portability::newLocalFromLocal(nsIAtom* local, nsHtml5AtomTable* interner return local; } -void -nsHtml5Portability::releaseString(nsString* str) -{ - delete str; -} - bool nsHtml5Portability::localEqualsBuffer(nsIAtom* local, char16_t* buf, int32_t offset, int32_t length) { @@ -95,55 +85,32 @@ nsHtml5Portability::localEqualsBuffer(nsIAtom* local, char16_t* buf, int32_t off } bool -nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(const char* lowerCaseLiteral, nsString* string) +nsHtml5Portability::lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + const char* lowerCaseLiteral, + nsHtml5String string) { - if (!string) { - return false; - } - const char* litPtr = lowerCaseLiteral; - const char16_t* strPtr = string->BeginReading(); - const char16_t* end = string->EndReading(); - char16_t litChar; - while ((litChar = *litPtr)) { - NS_ASSERTION(!(litChar >= 'A' && litChar <= 'Z'), "Literal isn't in lower case."); - if (strPtr == end) { - return false; - } - char16_t strChar = *strPtr; - if (strChar >= 'A' && strChar <= 'Z') { - strChar += 0x20; - } - if (litChar != strChar) { - return false; - } - ++litPtr; - ++strPtr; - } - return true; + return string.LowerCaseStartsWithASCII(lowerCaseLiteral); } bool -nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString(const char* lowerCaseLiteral, nsString* string) +nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( + const char* lowerCaseLiteral, + nsHtml5String string) { - if (!string) { - return false; - } - return string->LowerCaseEqualsASCII(lowerCaseLiteral); + return string.LowerCaseEqualsASCII(lowerCaseLiteral); } bool -nsHtml5Portability::literalEqualsString(const char* literal, nsString* string) +nsHtml5Portability::literalEqualsString(const char* literal, + nsHtml5String string) { - if (!string) { - return false; - } - return string->EqualsASCII(literal); + return string.EqualsASCII(literal); } bool -nsHtml5Portability::stringEqualsString(nsString* one, nsString* other) +nsHtml5Portability::stringEqualsString(nsHtml5String one, nsHtml5String other) { - return one->Equals(*other); + return one.Equals(other); } void diff --git a/parser/html/nsHtml5Portability.h b/parser/html/nsHtml5Portability.h index bd85ccbdb..a3214dd2f 100644 --- a/parser/html/nsHtml5Portability.h +++ b/parser/html/nsHtml5Portability.h @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -59,19 +59,26 @@ class nsHtml5Portability { public: static nsIAtom* newLocalNameFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner); - static nsString* newStringFromBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5TreeBuilder* treeBuilder); - static nsString* newEmptyString(); - static nsString* newStringFromLiteral(const char* literal); - static nsString* newStringFromString(nsString* string); + static nsHtml5String newStringFromBuffer(char16_t* buf, + int32_t offset, + int32_t length, + nsHtml5TreeBuilder* treeBuilder); + static nsHtml5String newEmptyString(); + static nsHtml5String newStringFromLiteral(const char* literal); + static nsHtml5String newStringFromString(nsHtml5String string); static jArray newCharArrayFromLocal(nsIAtom* local); - static jArray newCharArrayFromString(nsString* string); + static jArray newCharArrayFromString( + nsHtml5String string); static nsIAtom* newLocalFromLocal(nsIAtom* local, nsHtml5AtomTable* interner); - static void releaseString(nsString* str); static bool localEqualsBuffer(nsIAtom* local, char16_t* buf, int32_t offset, int32_t length); - static bool lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString(const char* lowerCaseLiteral, nsString* string); - static bool lowerCaseLiteralEqualsIgnoreAsciiCaseString(const char* lowerCaseLiteral, nsString* string); - static bool literalEqualsString(const char* literal, nsString* string); - static bool stringEqualsString(nsString* one, nsString* other); + static bool lowerCaseLiteralIsPrefixOfIgnoreAsciiCaseString( + const char* lowerCaseLiteral, + nsHtml5String string); + static bool lowerCaseLiteralEqualsIgnoreAsciiCaseString( + const char* lowerCaseLiteral, + nsHtml5String string); + static bool literalEqualsString(const char* literal, nsHtml5String string); + static bool stringEqualsString(nsHtml5String one, nsHtml5String other); static void initializeStatics(); static void releaseStatics(); }; diff --git a/parser/html/nsHtml5SpeculativeLoad.h b/parser/html/nsHtml5SpeculativeLoad.h index 575f6186d..6f1365bcf 100644 --- a/parser/html/nsHtml5SpeculativeLoad.h +++ b/parser/html/nsHtml5SpeculativeLoad.h @@ -35,45 +35,57 @@ class nsHtml5SpeculativeLoad { nsHtml5SpeculativeLoad(); ~nsHtml5SpeculativeLoad(); - inline void InitBase(const nsAString& aUrl) + inline void InitBase(nsHtml5String aUrl) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadBase; - mUrl.Assign(aUrl); + aUrl.ToString(mUrl); } - inline void InitMetaCSP(const nsAString& aCSP) { + inline void InitMetaCSP(nsHtml5String aCSP) + { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadCSP; + nsString csp; // Not Auto, because using it to hold nsStringBuffer* + aCSP.ToString(csp); mMetaCSP.Assign( - nsContentUtils::TrimWhitespace(aCSP)); + nsContentUtils::TrimWhitespace(csp)); } - inline void InitMetaReferrerPolicy(const nsAString& aReferrerPolicy) { + inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) + { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadMetaReferrer; + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicy.Assign( - nsContentUtils::TrimWhitespace(aReferrerPolicy)); + nsContentUtils::TrimWhitespace( + referrerPolicy)); } - inline void InitImage(const nsAString& aUrl, - const nsAString& aCrossOrigin, - const nsAString& aReferrerPolicy, - const nsAString& aSrcset, - const nsAString& aSizes) + inline void InitImage(nsHtml5String aUrl, + nsHtml5String aCrossOrigin, + nsHtml5String aReferrerPolicy, + nsHtml5String aSrcset, + nsHtml5String aSizes) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadImage; - mUrl.Assign(aUrl); - mCrossOrigin.Assign(aCrossOrigin); + aUrl.ToString(mUrl); + aCrossOrigin.ToString(mCrossOrigin); + nsString + referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* + aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicy.Assign( - nsContentUtils::TrimWhitespace(aReferrerPolicy)); - mSrcset.Assign(aSrcset); - mSizes.Assign(aSizes); + nsContentUtils::TrimWhitespace( + referrerPolicy)); + aSrcset.ToString(mSrcset); + aSizes.ToString(mSizes); } // elements have multiple nodes followed by an , @@ -97,49 +109,50 @@ class nsHtml5SpeculativeLoad { mOpCode = eSpeculativeLoadEndPicture; } - inline void InitPictureSource(const nsAString& aSrcset, - const nsAString& aSizes, - const nsAString& aType, - const nsAString& aMedia) + inline void InitPictureSource(nsHtml5String aSrcset, + nsHtml5String aSizes, + nsHtml5String aType, + nsHtml5String aMedia) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadPictureSource; - mSrcset.Assign(aSrcset); - mSizes.Assign(aSizes); - mTypeOrCharsetSourceOrDocumentMode.Assign(aType); - mMedia.Assign(aMedia); + aSrcset.ToString(mSrcset); + aSizes.ToString(mSizes); + aType.ToString(mTypeOrCharsetSourceOrDocumentMode); + aMedia.ToString(mMedia); } - inline void InitScript(const nsAString& aUrl, - const nsAString& aCharset, - const nsAString& aType, - const nsAString& aCrossOrigin, - const nsAString& aIntegrity, + inline void InitScript(nsHtml5String aUrl, + nsHtml5String aCharset, + nsHtml5String aType, + nsHtml5String aCrossOrigin, + nsHtml5String aIntegrity, bool aParserInHead) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript; - mUrl.Assign(aUrl); - mCharset.Assign(aCharset); - mTypeOrCharsetSourceOrDocumentMode.Assign(aType); - mCrossOrigin.Assign(aCrossOrigin); - mIntegrity.Assign(aIntegrity); + aUrl.ToString(mUrl); + aCharset.ToString(mCharset); + aType.ToString(mTypeOrCharsetSourceOrDocumentMode); + aCrossOrigin.ToString(mCrossOrigin); + aIntegrity.ToString(mIntegrity); } - inline void InitStyle(const nsAString& aUrl, const nsAString& aCharset, - const nsAString& aCrossOrigin, - const nsAString& aIntegrity) + inline void InitStyle(nsHtml5String aUrl, + nsHtml5String aCharset, + nsHtml5String aCrossOrigin, + nsHtml5String aIntegrity) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadStyle; - mUrl.Assign(aUrl); - mCharset.Assign(aCharset); - mCrossOrigin.Assign(aCrossOrigin); - mIntegrity.Assign(aIntegrity); + aUrl.ToString(mUrl); + aCharset.ToString(mCharset); + aCrossOrigin.ToString(mCrossOrigin); + aIntegrity.ToString(mIntegrity); } /** @@ -153,12 +166,12 @@ class nsHtml5SpeculativeLoad { * manifests seen by the parser thread have to maintain the queue order * relative to true speculative loads. See bug 541079. */ - inline void InitManifest(const nsAString& aUrl) + inline void InitManifest(nsHtml5String aUrl) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadManifest; - mUrl.Assign(aUrl); + aUrl.ToString(mUrl); } /** @@ -195,14 +208,13 @@ class nsHtml5SpeculativeLoad { mTypeOrCharsetSourceOrDocumentMode.Assign((char16_t)aMode); } - inline void InitPreconnect(const nsAString& aUrl, - const nsAString& aCrossOrigin) + inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) { NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadPreconnect; - mUrl.Assign(aUrl); - mCrossOrigin.Assign(aCrossOrigin); + aUrl.ToString(mUrl); + aCrossOrigin.ToString(mCrossOrigin); } void Perform(nsHtml5TreeOpExecutor* aExecutor); diff --git a/parser/html/nsHtml5StackNode.cpp b/parser/html/nsHtml5StackNode.cpp index ac5f0b2a3..41163ae40 100644 --- a/parser/html/nsHtml5StackNode.cpp +++ b/parser/html/nsHtml5StackNode.cpp @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5StackNode.h b/parser/html/nsHtml5StackNode.h index 57909ca9c..1677ec571 100644 --- a/parser/html/nsHtml5StackNode.h +++ b/parser/html/nsHtml5StackNode.h @@ -31,7 +31,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5StateSnapshot.cpp b/parser/html/nsHtml5StateSnapshot.cpp index e8e3debf0..90780738b 100644 --- a/parser/html/nsHtml5StateSnapshot.cpp +++ b/parser/html/nsHtml5StateSnapshot.cpp @@ -29,7 +29,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5StateSnapshot.h b/parser/html/nsHtml5StateSnapshot.h index 141b34340..119570499 100644 --- a/parser/html/nsHtml5StateSnapshot.h +++ b/parser/html/nsHtml5StateSnapshot.h @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5StreamParser.cpp b/parser/html/nsHtml5StreamParser.cpp index 83bf4d8b6..ab4548125 100644 --- a/parser/html/nsHtml5StreamParser.cpp +++ b/parser/html/nsHtml5StreamParser.cpp @@ -1261,7 +1261,7 @@ nsHtml5StreamParser::PreferredForInternalEncodingDecl(nsACString& aEncoding) } bool -nsHtml5StreamParser::internalEncodingDeclaration(nsString* aEncoding) +nsHtml5StreamParser::internalEncodingDeclaration(nsHtml5String aEncoding) { // This code needs to stay in sync with // nsHtml5MetaScanner::tryCharset. Unfortunately, the @@ -1270,9 +1270,10 @@ nsHtml5StreamParser::internalEncodingDeclaration(nsString* aEncoding) if (mCharsetSource >= kCharsetFromMetaTag) { // this threshold corresponds to "confident" in the HTML5 spec return false; } - + nsString newEncoding16; // Not Auto, because using it to hold nsStringBuffer* + aEncoding.ToString(newEncoding16); nsAutoCString newEncoding; - CopyUTF16toUTF8(*aEncoding, newEncoding); + CopyUTF16toUTF8(newEncoding16, newEncoding); if (!PreferredForInternalEncodingDecl(newEncoding)) { return false; diff --git a/parser/html/nsHtml5StreamParser.h b/parser/html/nsHtml5StreamParser.h index 9a38ba067..2560f84ab 100644 --- a/parser/html/nsHtml5StreamParser.h +++ b/parser/html/nsHtml5StreamParser.h @@ -145,7 +145,7 @@ class nsHtml5StreamParser : public nsICharsetDetectionObserver { /** * Tree builder uses this to report a late */ - bool internalEncodingDeclaration(nsString* aEncoding); + bool internalEncodingDeclaration(nsHtml5String aEncoding); // Not from an external interface diff --git a/parser/html/nsHtml5String.cpp b/parser/html/nsHtml5String.cpp new file mode 100644 index 000000000..d26eeaede --- /dev/null +++ b/parser/html/nsHtml5String.cpp @@ -0,0 +1,226 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsHtml5String.h" +#include "nsCharTraits.h" +#include "nsUTF8Utils.h" +#include "nsHtml5TreeBuilder.h" + +nsHtml5String::nsHtml5String(already_AddRefed aBuffer, + uint32_t aLength) + : mBuffer(aBuffer.take()) + , mLength(aLength) +{ + if (mBuffer) { + MOZ_ASSERT(aLength); + } else { + MOZ_ASSERT(!aLength || aLength == UINT32_MAX); + } +} + +void +nsHtml5String::ToString(nsAString& aString) +{ + if (mBuffer) { + mBuffer->ToString(mLength, aString); + } else { + aString.Truncate(); + if (mLength) { + aString.SetIsVoid(true); + } + } +} + +void +nsHtml5String::CopyToBuffer(char16_t* aBuffer) +{ + if (mBuffer) { + memcpy(aBuffer, mBuffer->Data(), mLength * sizeof(char16_t)); + } +} + +bool +nsHtml5String::LowerCaseEqualsASCII(const char* aLowerCaseLiteral) +{ + if (!mBuffer) { + if (mLength) { + // This string is null + return false; + } + // this string is empty + return !(*aLowerCaseLiteral); + } + return !nsCharTraits::compareLowerCaseToASCIINullTerminated( + reinterpret_cast(mBuffer->Data()), Length(), aLowerCaseLiteral); +} + +bool +nsHtml5String::EqualsASCII(const char* aLiteral) +{ + if (!mBuffer) { + if (mLength) { + // This string is null + return false; + } + // this string is empty + return !(*aLiteral); + } + return !nsCharTraits::compareASCIINullTerminated( + reinterpret_cast(mBuffer->Data()), Length(), aLiteral); +} + +bool +nsHtml5String::LowerCaseStartsWithASCII(const char* aLowerCaseLiteral) +{ + if (!mBuffer) { + if (mLength) { + // This string is null + return false; + } + // this string is empty + return !(*aLowerCaseLiteral); + } + const char* litPtr = aLowerCaseLiteral; + const char16_t* strPtr = reinterpret_cast(mBuffer->Data()); + const char16_t* end = strPtr + Length(); + char16_t litChar; + while ((litChar = *litPtr) && (strPtr != end)) { + MOZ_ASSERT(!(litChar >= 'A' && litChar <= 'Z'), + "Literal isn't in lower case."); + char16_t strChar = *strPtr; + if (strChar >= 'A' && strChar <= 'Z') { + strChar += 0x20; + } + if (litChar != strChar) { + return false; + } + ++litPtr; + ++strPtr; + } + return true; +} + +bool +nsHtml5String::Equals(nsHtml5String aOther) +{ + MOZ_ASSERT(operator bool()); + MOZ_ASSERT(aOther); + if (mLength != aOther.mLength) { + return false; + } + if (!mBuffer) { + return true; + } + MOZ_ASSERT(aOther.mBuffer); + return !memcmp( + mBuffer->Data(), aOther.mBuffer->Data(), Length() * sizeof(char16_t)); +} + +nsHtml5String +nsHtml5String::Clone() +{ + MOZ_ASSERT(operator bool()); + RefPtr ref(mBuffer); + return nsHtml5String(ref.forget(), mLength); +} + +void +nsHtml5String::Release() +{ + if (mBuffer) { + mBuffer->Release(); + mBuffer = nullptr; + } + mLength = UINT32_MAX; +} + +// static +nsHtml5String +nsHtml5String::FromBuffer(char16_t* aBuffer, + int32_t aLength, + nsHtml5TreeBuilder* aTreeBuilder) +{ + if (!aLength) { + return nsHtml5String(nullptr, 0U); + } + // Work with nsStringBuffer directly to make sure that storage is actually + // nsStringBuffer and to make sure the allocation strategy matches + // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and + // copy. + RefPtr buffer( + nsStringBuffer::Alloc((aLength + 1) * sizeof(char16_t))); + if (!buffer) { + if (!aTreeBuilder) { + MOZ_CRASH("Out of memory."); + } + aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); + buffer = nsStringBuffer::Alloc(2 * sizeof(char16_t)); + if (!buffer) { + MOZ_CRASH( + "Out of memory so badly that couldn't even allocate placeholder."); + } + char16_t* data = reinterpret_cast(buffer->Data()); + data[0] = 0xFFFD; + data[1] = 0; + return nsHtml5String(buffer.forget(), 1); + } + char16_t* data = reinterpret_cast(buffer->Data()); + memcpy(data, aBuffer, aLength * sizeof(char16_t)); + data[aLength] = 0; + return nsHtml5String(buffer.forget(), aLength); +} + +// static +nsHtml5String +nsHtml5String::FromLiteral(const char* aLiteral) +{ + size_t length = std::strlen(aLiteral); + if (!length) { + return nsHtml5String(nullptr, 0U); + } + // Work with nsStringBuffer directly to make sure that storage is actually + // nsStringBuffer and to make sure the allocation strategy matches + // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and + // copy. + RefPtr buffer( + nsStringBuffer::Alloc((length + 1) * sizeof(char16_t))); + if (!buffer) { + MOZ_CRASH("Out of memory."); + } + char16_t* data = reinterpret_cast(buffer->Data()); + LossyConvertEncoding8to16 converter(data); + converter.write(aLiteral, length); + data[length] = 0; + return nsHtml5String(buffer.forget(), length); +} + +// static +nsHtml5String +nsHtml5String::FromString(const nsAString& aString) +{ + auto length = aString.Length(); + if (!length) { + return nsHtml5String(nullptr, 0U); + } + RefPtr buffer = nsStringBuffer::FromString(aString); + if (buffer) { + return nsHtml5String(buffer.forget(), length); + } + buffer = nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)); + if (!buffer) { + MOZ_CRASH("Out of memory."); + } + char16_t* data = reinterpret_cast(buffer->Data()); + memcpy(data, aString.BeginReading(), length * sizeof(char16_t)); + data[length] = 0; + return nsHtml5String(buffer.forget(), length); +} + +// static +nsHtml5String +nsHtml5String::EmptyString() +{ + return nsHtml5String(nullptr, 0U); + +} \ No newline at end of file diff --git a/parser/html/nsHtml5String.h b/parser/html/nsHtml5String.h new file mode 100644 index 000000000..191bf6be8 --- /dev/null +++ b/parser/html/nsHtml5String.h @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsHtml5String_h +#define nsHtml5String_h + +#include "nsString.h" + +class nsHtml5TreeBuilder; + +/** + * A pass-by-value type that combines an unsafe `nsStringBuffer*` with its + * logical length (`uint32_t`). (`nsStringBuffer` knows its capacity but not + * its logical length, i.e. how much of the capacity is in use.) + * + * Holding or passing this type is as unsafe as holding or passing + * `nsStringBuffer*`. + * + * Empty strings and null strings are distinct. Since an empty nsString does + * not have a an `nsStringBuffer`, both empty and null `nsHtml5String` have + * `nullptr` as `mBuffer`. If `mBuffer` is `nullptr`, the empty case is marked + * with `mLength` being zero and the null case with `mLength` being non-zero. + */ +class nsHtml5String final +{ +public: + /** + * Default constructor. + */ + inline nsHtml5String() + : nsHtml5String(nullptr) + { + } + + /** + * Constructor from nullptr. + */ + inline MOZ_IMPLICIT nsHtml5String(decltype(nullptr)) + : mBuffer(nullptr) + , mLength(UINT32_MAX) + { + } + + inline uint32_t Length() const { return mBuffer ? mLength : 0; } + + /** + * False iff the string is logically null + */ + inline MOZ_IMPLICIT operator bool() const { return !(!mBuffer && mLength); } + + void ToString(nsAString& aString); + + void CopyToBuffer(char16_t* aBuffer); + + bool LowerCaseEqualsASCII(const char* aLowerCaseLiteral); + + bool EqualsASCII(const char* aLiteral); + + bool LowerCaseStartsWithASCII(const char* aLowerCaseLiteral); + + bool Equals(nsHtml5String aOther); + + nsHtml5String Clone(); + + void Release(); + + static nsHtml5String FromBuffer(char16_t* aBuffer, + int32_t aLength, + nsHtml5TreeBuilder* aTreeBuilder); + + static nsHtml5String FromLiteral(const char* aLiteral); + + static nsHtml5String FromString(const nsAString& aString); + + static nsHtml5String EmptyString(); + +private: + /** + * Constructor from raw parts. + */ + nsHtml5String(already_AddRefed aBuffer, uint32_t aLength); + + /** + * nullptr if the string is logically null or logically empty + */ + nsStringBuffer* mBuffer; + + /** + * The length of the string. non-zero if the string is logically null. + */ + uint32_t mLength; +}; + +#endif // nsHtml5String_h \ No newline at end of file diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 2838d74aa..a9db8d0c1 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -32,7 +32,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" #include "jArray.h" @@ -113,7 +113,8 @@ nsHtml5Tokenizer::setInterner(nsHtml5AtomTable* interner) } void -nsHtml5Tokenizer::initLocation(nsString* newPublicId, nsString* newSystemId) +nsHtml5Tokenizer::initLocation(nsHtml5String newPublicId, + nsHtml5String newSystemId) { this->systemId = newSystemId; this->publicId = newPublicId; @@ -222,10 +223,11 @@ nsHtml5Tokenizer::emitOrAppendCharRefBuf(int32_t returnState) } } -nsString* +nsHtml5String nsHtml5Tokenizer::strBufToString() { - nsString* str = nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen, tokenHandler); + nsHtml5String str = + nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen, tokenHandler); clearStrBufAfterUse(); return str; } @@ -350,7 +352,7 @@ void nsHtml5Tokenizer::addAttributeWithValue() { if (attributeName) { - nsString* val = strBufToString(); + nsHtml5String val = strBufToString(); if (mViewSource) { mViewSource->MaybeLinkifyAttributeValue(attributeName, val); } @@ -3496,11 +3498,11 @@ nsHtml5Tokenizer::initDoctypeFields() clearStrBufAfterUse(); doctypeName = nsHtml5Atoms::emptystring; if (systemIdentifier) { - nsHtml5Portability::releaseString(systemIdentifier); + systemIdentifier.Release(); systemIdentifier = nullptr; } if (publicIdentifier) { - nsHtml5Portability::releaseString(publicIdentifier); + publicIdentifier.Release(); publicIdentifier = nullptr; } forceQuirks = false; @@ -3662,11 +3664,11 @@ nsHtml5Tokenizer::eof() errEofInDoctype(); doctypeName = nsHtml5Atoms::emptystring; if (systemIdentifier) { - nsHtml5Portability::releaseString(systemIdentifier); + systemIdentifier.Release(); systemIdentifier = nullptr; } if (publicIdentifier) { - nsHtml5Portability::releaseString(publicIdentifier); + publicIdentifier.Release(); publicIdentifier = nullptr; } forceQuirks = true; @@ -3896,14 +3898,14 @@ nsHtml5Tokenizer::emitDoctypeToken(int32_t pos) cstart = pos + 1; tokenHandler->doctype(doctypeName, publicIdentifier, systemIdentifier, forceQuirks); doctypeName = nullptr; - nsHtml5Portability::releaseString(publicIdentifier); + publicIdentifier.Release(); publicIdentifier = nullptr; - nsHtml5Portability::releaseString(systemIdentifier); + systemIdentifier.Release(); systemIdentifier = nullptr; } bool -nsHtml5Tokenizer::internalEncodingDeclaration(nsString* internalCharset) +nsHtml5Tokenizer::internalEncodingDeclaration(nsHtml5String internalCharset) { if (encodingDeclarationHandler) { return encodingDeclarationHandler->internalEncodingDeclaration(internalCharset); @@ -3938,11 +3940,11 @@ nsHtml5Tokenizer::end() strBuf = nullptr; doctypeName = nullptr; if (systemIdentifier) { - nsHtml5Portability::releaseString(systemIdentifier); + systemIdentifier.Release(); systemIdentifier = nullptr; } if (publicIdentifier) { - nsHtml5Portability::releaseString(publicIdentifier); + publicIdentifier.Release(); publicIdentifier = nullptr; } if (tagName) { @@ -4041,13 +4043,13 @@ nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other) } else { doctypeName = nsHtml5Portability::newLocalFromLocal(other->doctypeName, interner); } - nsHtml5Portability::releaseString(systemIdentifier); + systemIdentifier.Release(); if (!other->systemIdentifier) { systemIdentifier = nullptr; } else { systemIdentifier = nsHtml5Portability::newStringFromString(other->systemIdentifier); } - nsHtml5Portability::releaseString(publicIdentifier); + publicIdentifier.Release(); if (!other->publicIdentifier) { publicIdentifier = nullptr; } else { diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h index da509b69b..00cca9a9c 100644 --- a/parser/html/nsHtml5Tokenizer.h +++ b/parser/html/nsHtml5Tokenizer.h @@ -33,7 +33,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" #include "jArray.h" @@ -106,8 +106,8 @@ class nsHtml5Tokenizer protected: int32_t cstart; private: - nsString* publicId; - nsString* systemId; + nsHtml5String publicId; + nsHtml5String systemId; autoJArray strBuf; int32_t strBufLen; autoJArray charRefBuf; @@ -126,8 +126,8 @@ class nsHtml5Tokenizer nsHtml5AttributeName* attributeName; private: nsIAtom* doctypeName; - nsString* publicIdentifier; - nsString* systemIdentifier; + nsHtml5String publicIdentifier; + nsHtml5String systemIdentifier; nsHtml5HtmlAttributes* attributes; bool newAttributesEachTime; bool shouldSuspend; @@ -141,7 +141,7 @@ class nsHtml5Tokenizer public: nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, bool viewingXmlSource); void setInterner(nsHtml5AtomTable* interner); - void initLocation(nsString* newPublicId, nsString* newSystemId); + void initLocation(nsHtml5String newPublicId, nsHtml5String newSystemId); bool isViewingXmlSource(); void setStateAndEndTagExpectation(int32_t specialTokenizerState, nsIAtom* endTagExpectation); void setStateAndEndTagExpectation(int32_t specialTokenizerState, nsHtml5ElementName* endTagExpectation); @@ -193,7 +193,7 @@ class nsHtml5Tokenizer } protected: - nsString* strBufToString(); + nsHtml5String strBufToString(); private: void strBufToDoctypeName(); void emitStrBuf(); @@ -285,7 +285,7 @@ class nsHtml5Tokenizer } public: - bool internalEncodingDeclaration(nsString* internalCharset); + bool internalEncodingDeclaration(nsHtml5String internalCharset); private: void emitOrAppendTwo(const char16_t* val, int32_t returnState); void emitOrAppendOne(const char16_t* val, int32_t returnState); diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index f694116ba..457c7deb1 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -34,7 +34,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" #include "nsITimer.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -154,13 +154,16 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) } void -nsHtml5TreeBuilder::doctype(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, bool forceQuirks) +nsHtml5TreeBuilder::doctype(nsIAtom* name, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool forceQuirks) { needToDropLF = false; if (!isInForeign() && mode == NS_HTML5TREE_BUILDER_INITIAL) { - nsString* emptyString = nsHtml5Portability::newEmptyString(); + nsHtml5String emptyString = nsHtml5Portability::newEmptyString(); appendDoctypeToDocument(!name ? nsHtml5Atoms::emptystring : name, !publicIdentifier ? emptyString : publicIdentifier, !systemIdentifier ? emptyString : systemIdentifier); - nsHtml5Portability::releaseString(emptyString); + emptyString.Release(); if (isQuirky(name, publicIdentifier, systemIdentifier, forceQuirks)) { errQuirkyDoctype(); documentModeInternal(QUIRKS_MODE, publicIdentifier, systemIdentifier, false); @@ -1990,8 +1993,9 @@ nsHtml5TreeBuilder::isSpecialParentInForeign(nsHtml5StackNode* stackNode) return (kNameSpaceID_XHTML == ns) || (stackNode->isHtmlIntegrationPoint()) || ((kNameSpaceID_MathML == ns) && (stackNode->getGroup() == NS_HTML5TREE_BUILDER_MI_MO_MN_MS_MTEXT)); } -nsString* -nsHtml5TreeBuilder::extractCharsetFromContent(nsString* attributeValue, nsHtml5TreeBuilder* tb) +nsHtml5String +nsHtml5TreeBuilder::extractCharsetFromContent(nsHtml5String attributeValue, + nsHtml5TreeBuilder* tb) { int32_t charsetState = NS_HTML5TREE_BUILDER_CHARSET_INITIAL; int32_t start = -1; @@ -2175,12 +2179,13 @@ nsHtml5TreeBuilder::extractCharsetFromContent(nsString* attributeValue, nsHtml5T } } charsetloop_end: ; - nsString* charset = nullptr; + nsHtml5String charset = nullptr; if (start != -1) { if (end == -1) { end = buffer.length; } - charset = nsHtml5Portability::newStringFromBuffer(buffer, start, end - start, tb); + charset = + nsHtml5Portability::newStringFromBuffer(buffer, start, end - start, tb); } return charset; } @@ -2188,7 +2193,8 @@ nsHtml5TreeBuilder::extractCharsetFromContent(nsString* attributeValue, nsHtml5T void nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) { - nsString* charset = attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + nsHtml5String charset = + attributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); if (charset) { if (tokenizer->internalEncodingDeclaration(charset)) { requestSuspension(); @@ -2199,15 +2205,17 @@ nsHtml5TreeBuilder::checkMetaCharset(nsHtml5HtmlAttributes* attributes) if (!nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("content-type", attributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) { return; } - nsString* content = attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); + nsHtml5String content = + attributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); if (content) { - nsString* extract = nsHtml5TreeBuilder::extractCharsetFromContent(content, this); + nsHtml5String extract = + nsHtml5TreeBuilder::extractCharsetFromContent(content, this); if (extract) { if (tokenizer->internalEncodingDeclaration(extract)) { requestSuspension(); } } - nsHtml5Portability::releaseString(extract); + extract.Release(); } } @@ -3208,7 +3216,11 @@ nsHtml5TreeBuilder::isSecondOnStackBody() } void -nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m, nsString* publicIdentifier, nsString* systemIdentifier, bool html4SpecificAdditionalErrorChecks) +nsHtml5TreeBuilder::documentModeInternal( + nsHtml5DocumentMode m, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool html4SpecificAdditionalErrorChecks) { if (isSrcdocDocument) { quirks = false; @@ -3220,7 +3232,8 @@ nsHtml5TreeBuilder::documentModeInternal(nsHtml5DocumentMode m, nsString* public } bool -nsHtml5TreeBuilder::isAlmostStandards(nsString* publicIdentifier, nsString* systemIdentifier) +nsHtml5TreeBuilder::isAlmostStandards(nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier) { if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString("-//w3c//dtd xhtml 1.0 transitional//en", publicIdentifier)) { return true; @@ -3240,7 +3253,10 @@ nsHtml5TreeBuilder::isAlmostStandards(nsString* publicIdentifier, nsString* syst } bool -nsHtml5TreeBuilder::isQuirky(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, bool forceQuirks) +nsHtml5TreeBuilder::isQuirky(nsIAtom* name, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool forceQuirks) { if (forceQuirks) { return true; @@ -4051,7 +4067,8 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5Elem bool nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes) { - nsString* encoding = attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING); + nsHtml5String encoding = + attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING); if (!encoding) { return false; } diff --git a/parser/html/nsHtml5TreeBuilder.h b/parser/html/nsHtml5TreeBuilder.h index a66b168be..67f5010c5 100644 --- a/parser/html/nsHtml5TreeBuilder.h +++ b/parser/html/nsHtml5TreeBuilder.h @@ -35,7 +35,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" #include "nsITimer.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" @@ -103,7 +103,10 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState bool isSrcdocDocument; public: void startTokenization(nsHtml5Tokenizer* self); - void doctype(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, bool forceQuirks); + void doctype(nsIAtom* name, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool forceQuirks); void comment(char16_t* buf, int32_t start, int32_t length); void characters(const char16_t* buf, int32_t start, int32_t length); void zeroOriginatingReplacementCharacter(); @@ -119,7 +122,8 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState bool isTemplateModeStackEmpty(); bool isSpecialParentInForeign(nsHtml5StackNode* stackNode); public: - static nsString* extractCharsetFromContent(nsString* attributeValue, nsHtml5TreeBuilder* tb); + static nsHtml5String extractCharsetFromContent(nsHtml5String attributeValue, + nsHtml5TreeBuilder* tb); private: void checkMetaCharset(nsHtml5HtmlAttributes* attributes); public: @@ -136,9 +140,16 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState void generateImpliedEndTagsExceptFor(nsIAtom* name); void generateImpliedEndTags(); bool isSecondOnStackBody(); - void documentModeInternal(nsHtml5DocumentMode m, nsString* publicIdentifier, nsString* systemIdentifier, bool html4SpecificAdditionalErrorChecks); - bool isAlmostStandards(nsString* publicIdentifier, nsString* systemIdentifier); - bool isQuirky(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier, bool forceQuirks); + void documentModeInternal(nsHtml5DocumentMode m, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool html4SpecificAdditionalErrorChecks); + bool isAlmostStandards(nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier); + bool isQuirky(nsIAtom* name, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier, + bool forceQuirks); void closeTheCell(int32_t eltPos); int32_t findLastInTableScopeTdTh(); void clearStackBackTo(int32_t eltPos); @@ -224,7 +235,9 @@ class nsHtml5TreeBuilder : public nsAHtml5TreeBuilderState void markMalformedIfScript(nsIContentHandle* elt); void start(bool fragmentMode); void end(); - void appendDoctypeToDocument(nsIAtom* name, nsString* publicIdentifier, nsString* systemIdentifier); + void appendDoctypeToDocument(nsIAtom* name, + nsHtml5String publicIdentifier, + nsHtml5String systemIdentifier); void elementPushed(int32_t ns, nsIAtom* name, nsIContentHandle* node); void elementPopped(int32_t ns, nsIAtom* name, nsIContentHandle* node); public: diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index ff17c326e..aacc5a3e0 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -123,181 +123,178 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, switch (aNamespace) { case kNameSpaceID_XHTML: if (nsHtml5Atoms::img == aName) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); - nsString* srcset = + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); + nsHtml5String srcset = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET); - nsString* crossOrigin = + nsHtml5String crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - nsString* referrerPolicy = + nsHtml5String referrerPolicy = aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY); - nsString* sizes = + nsHtml5String sizes = aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES); - mSpeculativeLoadQueue.AppendElement()-> - InitImage(url ? *url : NullString(), - crossOrigin ? *crossOrigin : NullString(), - referrerPolicy ? *referrerPolicy : NullString(), - srcset ? *srcset : NullString(), - sizes ? *sizes : NullString()); + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, crossOrigin, referrerPolicy, srcset, sizes); } else if (nsHtml5Atoms::source == aName) { - nsString* srcset = + nsHtml5String srcset = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRCSET); // Sources without srcset cannot be selected. The source could also be // for a media element, but in that context doesn't use srcset. See // comments in nsHtml5SpeculativeLoad.h about preloading if (srcset) { - nsString* sizes = + nsHtml5String sizes = aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES); - nsString* type = + nsHtml5String type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); - nsString* media = + nsHtml5String media = aAttributes->getValue(nsHtml5AttributeName::ATTR_MEDIA); - mSpeculativeLoadQueue.AppendElement()-> - InitPictureSource(*srcset, - sizes ? *sizes : NullString(), - type ? *type : NullString(), - media ? *media : NullString()); + mSpeculativeLoadQueue.AppendElement()->InitPictureSource( + srcset, sizes, type, media); } } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber()); - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_SRC); if (url) { - nsString* charset = aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); - nsString* type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); - nsString* crossOrigin = + nsHtml5String charset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + nsHtml5String type = + aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); + nsHtml5String crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - nsString* integrity = + nsHtml5String integrity = aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); - mSpeculativeLoadQueue.AppendElement()-> - InitScript(*url, - (charset) ? *charset : EmptyString(), - (type) ? *type : EmptyString(), - (crossOrigin) ? *crossOrigin : NullString(), - (integrity) ? *integrity : NullString(), - mode == NS_HTML5TREE_BUILDER_IN_HEAD); + mSpeculativeLoadQueue.AppendElement()->InitScript( + url, + charset, + type, + crossOrigin, + integrity, + mode == NS_HTML5TREE_BUILDER_IN_HEAD); mCurrentHtmlScriptIsAsyncOrDefer = aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) || aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER); } } else if (nsHtml5Atoms::link == aName) { - nsString* rel = aAttributes->getValue(nsHtml5AttributeName::ATTR_REL); + nsHtml5String rel = + aAttributes->getValue(nsHtml5AttributeName::ATTR_REL); // Not splitting on space here is bogus but the old parser didn't even // do a case-insensitive check. if (rel) { - if (rel->LowerCaseEqualsASCII("stylesheet")) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + if (rel.LowerCaseEqualsASCII("stylesheet")) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); if (url) { - nsString* charset = aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); - nsString* crossOrigin = + nsHtml5String charset = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET); + nsHtml5String crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - nsString* integrity = + nsHtml5String integrity = aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); - mSpeculativeLoadQueue.AppendElement()-> - InitStyle(*url, - (charset) ? *charset : EmptyString(), - (crossOrigin) ? *crossOrigin : NullString(), - (integrity) ? *integrity : NullString()); + mSpeculativeLoadQueue.AppendElement()->InitStyle( + url, charset, crossOrigin, integrity); } - } else if (rel->LowerCaseEqualsASCII("preconnect")) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + } else if (rel.LowerCaseEqualsASCII("preconnect")) { + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); if (url) { - nsString* crossOrigin = + nsHtml5String crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - mSpeculativeLoadQueue.AppendElement()-> - InitPreconnect(*url, (crossOrigin) ? *crossOrigin : NullString()); + mSpeculativeLoadQueue.AppendElement()->InitPreconnect( + url, crossOrigin); } } } } else if (nsHtml5Atoms::video == aName) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER); if (url) { - mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString(), - NullString(), - NullString(), - NullString()); + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, nullptr, nullptr, nullptr, nullptr); } } else if (nsHtml5Atoms::style == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber()); } else if (nsHtml5Atoms::html == aName) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST); - if (url) { - mSpeculativeLoadQueue.AppendElement()->InitManifest(*url); - } else { - mSpeculativeLoadQueue.AppendElement()->InitManifest(EmptyString()); - } + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST); + mSpeculativeLoadQueue.AppendElement()->InitManifest(url); } else if (nsHtml5Atoms::base == aName) { - nsString* url = - aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); if (url) { - mSpeculativeLoadQueue.AppendElement()->InitBase(*url); + mSpeculativeLoadQueue.AppendElement()->InitBase(url); } } else if (nsHtml5Atoms::meta == aName) { if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( "content-security-policy", aAttributes->getValue(nsHtml5AttributeName::ATTR_HTTP_EQUIV))) { - nsString* csp = aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); + nsHtml5String csp = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); if (csp) { - mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(*csp); + mSpeculativeLoadQueue.AppendElement()->InitMetaCSP(csp); } } else if (nsHtml5Portability::lowerCaseLiteralEqualsIgnoreAsciiCaseString( "referrer", aAttributes->getValue(nsHtml5AttributeName::ATTR_NAME))) { - nsString* referrerPolicy = aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); + nsHtml5String referrerPolicy = + aAttributes->getValue(nsHtml5AttributeName::ATTR_CONTENT); if (referrerPolicy) { - mSpeculativeLoadQueue.AppendElement()->InitMetaReferrerPolicy(*referrerPolicy); + mSpeculativeLoadQueue.AppendElement()->InitMetaReferrerPolicy( + referrerPolicy); } } } break; case kNameSpaceID_SVG: if (nsHtml5Atoms::image == aName) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); if (url) { - mSpeculativeLoadQueue.AppendElement()->InitImage(*url, NullString(), - NullString(), - NullString(), - NullString()); + mSpeculativeLoadQueue.AppendElement()->InitImage( + url, nullptr, nullptr, nullptr, nullptr); } } else if (nsHtml5Atoms::script == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); treeOp->Init(eTreeOpSetScriptLineNumberAndFreeze, content, tokenizer->getLineNumber()); - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); if (url) { - nsString* type = aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); - nsString* crossOrigin = + nsHtml5String type = + aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE); + nsHtml5String crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - nsString* integrity = + nsHtml5String integrity = aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); - mSpeculativeLoadQueue.AppendElement()-> - InitScript(*url, - EmptyString(), - (type) ? *type : EmptyString(), - (crossOrigin) ? *crossOrigin : NullString(), - (integrity) ? *integrity : NullString(), - mode == NS_HTML5TREE_BUILDER_IN_HEAD); + mSpeculativeLoadQueue.AppendElement()->InitScript( + url, + nullptr, + type, + crossOrigin, + integrity, + mode == NS_HTML5TREE_BUILDER_IN_HEAD); } } else if (nsHtml5Atoms::style == aName) { nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); treeOp->Init(eTreeOpSetStyleLineNumber, content, tokenizer->getLineNumber()); - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF); if (url) { - nsString* crossOrigin = + nsHtml5String crossOrigin = aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN); - nsString* integrity = + nsHtml5String integrity = aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY); - mSpeculativeLoadQueue.AppendElement()-> - InitStyle(*url, EmptyString(), - (crossOrigin) ? *crossOrigin : NullString(), - (integrity) ? *integrity : NullString()); + mSpeculativeLoadQueue.AppendElement()->InitStyle( + url, nullptr, crossOrigin, integrity); } } break; @@ -320,18 +317,23 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, } } else if (aNamespace == kNameSpaceID_XHTML) { if (nsHtml5Atoms::html == aName) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_MANIFEST); nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); if (url) { - treeOp->Init(eTreeOpProcessOfflineManifest, *url); + nsString + urlString; // Not Auto, because using it to hold nsStringBuffer* + url.ToString(urlString); + treeOp->Init(eTreeOpProcessOfflineManifest, urlString); } else { treeOp->Init(eTreeOpProcessOfflineManifest, EmptyString()); } } else if (nsHtml5Atoms::base == aName && mViewSource) { - nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); + nsHtml5String url = + aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); if (url) { - mViewSource->AddBase(*url); + mViewSource->AddBase(url); } } } @@ -743,17 +745,19 @@ nsHtml5TreeBuilder::end() } void -nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId, nsString* aSystemId) +nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, + nsHtml5String aPublicId, + nsHtml5String aSystemId) { NS_PRECONDITION(aName, "Null name"); - + nsString publicId; // Not Auto, because using it to hold nsStringBuffer* + nsString systemId; // Not Auto, because using it to hold nsStringBuffer* + aPublicId.ToString(publicId); + aSystemId.ToString(systemId); if (mBuilder) { nsCOMPtr name = nsHtml5TreeOperation::Reget(aName); - nsresult rv = - nsHtml5TreeOperation::AppendDoctypeToDocument(name, - *aPublicId, - *aSystemId, - mBuilder); + nsresult rv = nsHtml5TreeOperation::AppendDoctypeToDocument( + name, publicId, systemId, mBuilder); if (NS_FAILED(rv)) { MarkAsBrokenAndRequestSuspension(rv); } @@ -762,7 +766,7 @@ nsHtml5TreeBuilder::appendDoctypeToDocument(nsIAtom* aName, nsString* aPublicId, nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement(); NS_ASSERTION(treeOp, "Tree op allocation failed."); - treeOp->Init(aName, *aPublicId, *aSystemId); + treeOp->Init(aName, publicId, systemId); // nsXMLContentSink can flush here, but what's the point? // It can also interrupt here, but we can't. } diff --git a/parser/html/nsHtml5TreeOperation.cpp b/parser/html/nsHtml5TreeOperation.cpp index af246a253..3877e01b8 100644 --- a/parser/html/nsHtml5TreeOperation.cpp +++ b/parser/html/nsHtml5TreeOperation.cpp @@ -319,11 +319,10 @@ nsHtml5TreeOperation::AddAttributes(nsIContent* aNode, if (!node->HasAttr(nsuri, localName)) { // prefix doesn't need regetting. it is always null or a static atom // local name is never null - node->SetAttr(nsuri, - localName, - aAttributes->getPrefixNoBoundsCheck(i), - *(aAttributes->getValueNoBoundsCheck(i)), - true); + nsString value; // Not Auto, because using it to hold nsStringBuffer* + aAttributes->getValueNoBoundsCheck(i).ToString(value); + node->SetAttr( + nsuri, localName, aAttributes->getPrefixNoBoundsCheck(i), value, true); // XXX what to do with nsresult? } } @@ -418,12 +417,14 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs, nsCOMPtr prefix = aAttributes->getPrefixNoBoundsCheck(i); int32_t nsuri = aAttributes->getURINoBoundsCheck(i); + nsString value; // Not Auto, because using it to hold nsStringBuffer* + aAttributes->getValueNoBoundsCheck(i).ToString(value); if (aNs == kNameSpaceID_XHTML && nsHtml5Atoms::a == aName && nsHtml5Atoms::name == localName) { // This is an HTML5-incompliant Geckoism. // Remove when fixing bug 582361 - NS_ConvertUTF16toUTF8 cname(*(aAttributes->getValueNoBoundsCheck(i))); + NS_ConvertUTF16toUTF8 cname(value); NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting())); newContent->SetAttr(nsuri, localName, @@ -431,7 +432,6 @@ nsHtml5TreeOperation::CreateElement(int32_t aNs, uv, false); } else { - nsString& value = *(aAttributes->getValueNoBoundsCheck(i)); newContent->SetAttr(nsuri, localName, prefix, diff --git a/parser/html/nsHtml5UTF16Buffer.cpp b/parser/html/nsHtml5UTF16Buffer.cpp index f70365ce4..0d6870bc4 100644 --- a/parser/html/nsHtml5UTF16Buffer.cpp +++ b/parser/html/nsHtml5UTF16Buffer.cpp @@ -29,7 +29,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5UTF16Buffer.h b/parser/html/nsHtml5UTF16Buffer.h index cf810e124..c94245f74 100644 --- a/parser/html/nsHtml5UTF16Buffer.h +++ b/parser/html/nsHtml5UTF16Buffer.h @@ -30,7 +30,7 @@ #include "nsIAtom.h" #include "nsHtml5AtomTable.h" -#include "nsString.h" +#include "nsHtml5String.h" #include "nsNameSpaceManager.h" #include "nsIContent.h" #include "nsTraceRefcnt.h" diff --git a/parser/html/nsHtml5ViewSourceUtils.cpp b/parser/html/nsHtml5ViewSourceUtils.cpp index 4dd33fc05..b2f635bff 100644 --- a/parser/html/nsHtml5ViewSourceUtils.cpp +++ b/parser/html/nsHtml5ViewSourceUtils.cpp @@ -6,32 +6,35 @@ #include "nsHtml5ViewSourceUtils.h" #include "nsHtml5AttributeName.h" #include "mozilla/Preferences.h" -#include "mozilla/UniquePtr.h" +#include "nsHtml5String.h" // static nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewBodyAttributes() { nsHtml5HtmlAttributes* bodyAttrs = new nsHtml5HtmlAttributes(0); - auto id = MakeUnique(NS_LITERAL_STRING("viewsource")); - bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, id.release(), -1); + nsHtml5String id = nsHtml5Portability::newStringFromLiteral("viewsource"); + bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_ID, id, -1); - auto klass = MakeUnique(); + nsString klass; if (mozilla::Preferences::GetBool("view_source.wrap_long_lines", true)) { - klass->Append(NS_LITERAL_STRING("wrap ")); + klass.Append(NS_LITERAL_STRING("wrap ")); } if (mozilla::Preferences::GetBool("view_source.syntax_highlight", true)) { - klass->Append(NS_LITERAL_STRING("highlight")); + klass.Append(NS_LITERAL_STRING("highlight")); } - if (!klass->IsEmpty()) { - bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_CLASS, klass.release(), -1); + if (!klass.IsEmpty()) { + bodyAttrs->addAttribute( + nsHtml5AttributeName::ATTR_CLASS, nsHtml5String::FromString(klass), -1); } int32_t tabSize = mozilla::Preferences::GetInt("view_source.tab_size", 4); if (tabSize > 0) { - auto style = MakeUnique(NS_LITERAL_STRING("-moz-tab-size: ")); - style->AppendInt(tabSize); - bodyAttrs->addAttribute(nsHtml5AttributeName::ATTR_STYLE, style.release(), -1); + nsString style; + style.AssignASCII("-moz-tab-size: "); + style.AppendInt(tabSize); + bodyAttrs->addAttribute( + nsHtml5AttributeName::ATTR_STYLE, nsHtml5String::FromString(style), -1); } return bodyAttrs; @@ -42,12 +45,12 @@ nsHtml5HtmlAttributes* nsHtml5ViewSourceUtils::NewLinkAttributes() { nsHtml5HtmlAttributes* linkAttrs = new nsHtml5HtmlAttributes(0); - nsString* rel = new nsString(NS_LITERAL_STRING("stylesheet")); + nsHtml5String rel = nsHtml5Portability::newStringFromLiteral("stylesheet"); linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_REL, rel, -1); - nsString* type = new nsString(NS_LITERAL_STRING("text/css")); + nsHtml5String type = nsHtml5Portability::newStringFromLiteral("text/css"); linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TYPE, type, -1); - nsString* href = new nsString( - NS_LITERAL_STRING("resource://gre-resources/viewsource.css")); + nsHtml5String href = nsHtml5Portability::newStringFromLiteral( + "resource://gre-resources/viewsource.css"); linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1); return linkAttrs; } -- cgit v1.2.3