Title: [261437] trunk
Revision
261437
Author
[email protected]
Date
2020-05-09 09:04:01 -0700 (Sat, 09 May 2020)

Log Message

Streamline MarkupAccumulator to improve efficiency a bit
https://bugs.webkit.org/show_bug.cgi?id=211656

Reviewed by Anders Carlsson.

Source/_javascript_Core:

* b3/air/AirFixPartialRegisterStalls.h: Fix spelling of "explicitly".

Source/WebCore:

* editing/MarkupAccumulator.cpp:
(WebCore::MarkupAccumulator::appendCharactersReplacingEntities): Corrected early
exit so it returns any time the length is 0. For some reason the code before
wouldn't do the early return when offset is non-zero, which is unnecessary.
(WebCore::MarkupAccumulator::appendString): Deleted.
(WebCore::MarkupAccumulator::appendStringView): Deleted.
(WebCore::MarkupAccumulator::appendEndTag): Use variadic append to cut down
on memory allocations.
(WebCore::MarkupAccumulator::totalLength): Deleted.
(WebCore::MarkupAccumulator::concatenateMarkup): Deleted.
(WebCore::MarkupAccumulator::takeMarkup): Added.
(WebCore::MarkupAccumulator::appendQuotedURLAttributeValue): Use variadic
append to cut down on memory allocations. Also use char instead of UChar so
the string building code doesn't have to do an 8/16 bit check.
(WebCore::shouldAddNamespaceElement): Prepend a literal, don't bother to
make a String just to append to another String. Also made this a
non-member function.
(WebCore::shouldAddNamespaceAttribute): Made this a non-member function.
(WebCore::MarkupAccumulator::appendNamespace): Fix hash table usage
to use add instead of get followed by set to avoid double hashing.
Use variadic append to cut down on memory allocation.
(WebCore::MarkupAccumulator::appendText): Tweaked style to make this a
one-line function.
(WebCore::appendComment): Deleted.
(WebCore::appendXMLDeclaration): Made this a non-member function.
Use variadic append to cut down on memory allocation.
(WebCore::appendDocumentType): Made this a non-member function.
Use variadic append to cut down on memory allocation.
(WebCore::MarkupAccumulator::appendCDATASection): Deleted.
(WebCore::MarkupAccumulator::appendNonElementNode): Moved the bodies of
appendComment, appendProcessingInstruction, and appendCDATASection in
here since they can all be one-line variadic append calls.

* editing/MarkupAccumulator.h:
(WebCore::MarkupAccumulator::length const): Changed the return type
of length to be unsigned since that's what StringBuilder returns.
Made isAllASCII call StringBuilder::isAllASCII. Replaced appendString
and appendStringView with variadic append. Removed many functions
that no longer need to be member functions. Made appendAttributeValue
a static member function. Made appendNamespace private. Made
m_serializationSyntax const.

* editing/markup.cpp:
(WebCore::StyledMarkupAccumulator::wrapWithStyleNode): Use append
instead of appenString.
(WebCore::StyledMarkupAccumulator::isAllASCII const): Added. Before
the code would only check the StringBuilder, but we also need to
check m_reversedPrecedingMarkup.
(WebCore::StyledMarkupAccumulator::takeResults): Use CheckedUint32
since StringBuilder's reserveCapacity function takes unsigned, not
size_t. The old code, using totalLength, would just pass a size_t
and let it get chopped off, which didn't do any harm, but it seems
strange to compute a 64-bit value just to chop off the lower 32
bits. An alternative is to compute the 32-bit value and just let
it overflow. Use a modern for loop by defining a ReverseView
template rather than writing a confusing backwards loop. Use the
new takeMarkup instead of concatenateMarkup.
(WebCore::StyledMarkupAccumulator::appendText): Tweak coding
style a little bit.
(WebCore::StyledMarkupAccumulator::appendStartTag): Ditto.
(WebCore::StyledMarkupAccumulator::appendNodeToPreserveMSOList):
Use variadic append to cut down on memory allocations.
(WebCore::propertyMissingOrEqualToNone): Tweak coding style a bit.
(WebCore::serializePreservingVisualAppearanceInternal): Use
append instead of appendString.
(WebCore::shouldPreserveMSOLists): Take a StringView instead of a
String to eliminate unnecessary memory allocation in call to substring.
(WebCore::sanitizedMarkupForFragmentInDocument): Use makeString
instead of StringBuilder to cut down on memory allocation.

* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::resetDefaultButton): Fix spelling error
in the word "explicitly".
* mathml/MathMLOperatorDictionary.cpp:
(WebCore::MathMLOperatorDictionary::search): Ditto.

* page/PageSerializer.cpp:
(WebCore::PageSerializer::SerializerMarkupAccumulator::SerializerMarkupAccumulator):
Use variadic append instead of appendString to cut down on
memory allocations.

* rendering/svg/SVGInlineTextBox.cpp:
(WebCore::SVGInlineTextBox::paint): Fix spelling error in the word
"explicitly".

Source/WTF:

* wtf/text/StringBuilder.cpp:
(WTF::StringBuilder::isAllASCII const): Added.
* wtf/text/StringBuilder.h: Added isAllASCII.

Tools:

* TestWebKitAPI/Tests/WTF/StringImpl.cpp:
(TestWebKitAPI::TEST): Fix spellling error in the word "explicitly".

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (261436 => 261437)


--- trunk/Source/_javascript_Core/ChangeLog	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-05-09 16:04:01 UTC (rev 261437)
@@ -1,3 +1,12 @@
+2020-05-08  Darin Adler  <[email protected]>
+
+        Streamline MarkupAccumulator to improve efficiency a bit
+        https://bugs.webkit.org/show_bug.cgi?id=211656
+
+        Reviewed by Anders Carlsson.
+
+        * b3/air/AirFixPartialRegisterStalls.h: Fix spelling of "explicitly".
+
 2020-05-08  Alexey Shvayka  <[email protected]>
 
         Array.prototype.concat fast path checks should not be observable

Modified: trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.h (261436 => 261437)


--- trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.h	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/_javascript_Core/b3/air/AirFixPartialRegisterStalls.h	2020-05-09 16:04:01 UTC (rev 261437)
@@ -35,7 +35,7 @@
 //
 // Some instructions update only part of a register, they can only be scheduled after
 // the previous definition is computed. This problem can be avoided by the compiler
-// by explicitely resetting the entire register before executing the instruction with
+// by explicitly resetting the entire register before executing the instruction with
 // partial update.
 //
 // See "Partial XMM Register Stalls" and "Dependency Breaking Idioms" in the manual.

Modified: trunk/Source/WTF/ChangeLog (261436 => 261437)


--- trunk/Source/WTF/ChangeLog	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WTF/ChangeLog	2020-05-09 16:04:01 UTC (rev 261437)
@@ -1,3 +1,14 @@
+2020-05-08  Darin Adler  <[email protected]>
+
+        Streamline MarkupAccumulator to improve efficiency a bit
+        https://bugs.webkit.org/show_bug.cgi?id=211656
+
+        Reviewed by Anders Carlsson.
+
+        * wtf/text/StringBuilder.cpp:
+        (WTF::StringBuilder::isAllASCII const): Added.
+        * wtf/text/StringBuilder.h: Added isAllASCII.
+
 2020-05-09  David Quesada  <[email protected]>
 
         Remove HAVE_UI_SCROLL_VIEW_INDICATOR_FLASHING_SPI

Modified: trunk/Source/WTF/wtf/text/StringBuilder.cpp (261436 => 261437)


--- trunk/Source/WTF/wtf/text/StringBuilder.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WTF/wtf/text/StringBuilder.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -456,4 +456,14 @@
     }
 }
 
+bool StringBuilder::isAllASCII() const
+{
+    auto length = this->length();
+    if (!length)
+        return true;
+    if (m_is8Bit)
+        return charactersAreAllASCII(characters8(), length);
+    return charactersAreAllASCII(characters16(), length);
+}
+
 } // namespace WTF

Modified: trunk/Source/WTF/wtf/text/StringBuilder.h (261436 => 261437)


--- trunk/Source/WTF/wtf/text/StringBuilder.h	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WTF/wtf/text/StringBuilder.h	2020-05-09 16:04:01 UTC (rev 261437)
@@ -325,6 +325,7 @@
     }
     
     bool is8Bit() const { return m_is8Bit; }
+    WTF_EXPORT_PRIVATE bool isAllASCII() const;
 
     void clear()
     {

Modified: trunk/Source/WebCore/ChangeLog (261436 => 261437)


--- trunk/Source/WebCore/ChangeLog	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/ChangeLog	2020-05-09 16:04:01 UTC (rev 261437)
@@ -1,3 +1,95 @@
+2020-05-08  Darin Adler  <[email protected]>
+
+        Streamline MarkupAccumulator to improve efficiency a bit
+        https://bugs.webkit.org/show_bug.cgi?id=211656
+
+        Reviewed by Anders Carlsson.
+
+        * editing/MarkupAccumulator.cpp:
+        (WebCore::MarkupAccumulator::appendCharactersReplacingEntities): Corrected early
+        exit so it returns any time the length is 0. For some reason the code before
+        wouldn't do the early return when offset is non-zero, which is unnecessary.
+        (WebCore::MarkupAccumulator::appendString): Deleted.
+        (WebCore::MarkupAccumulator::appendStringView): Deleted.
+        (WebCore::MarkupAccumulator::appendEndTag): Use variadic append to cut down
+        on memory allocations.
+        (WebCore::MarkupAccumulator::totalLength): Deleted.
+        (WebCore::MarkupAccumulator::concatenateMarkup): Deleted.
+        (WebCore::MarkupAccumulator::takeMarkup): Added.
+        (WebCore::MarkupAccumulator::appendQuotedURLAttributeValue): Use variadic
+        append to cut down on memory allocations. Also use char instead of UChar so
+        the string building code doesn't have to do an 8/16 bit check.
+        (WebCore::shouldAddNamespaceElement): Prepend a literal, don't bother to
+        make a String just to append to another String. Also made this a
+        non-member function.
+        (WebCore::shouldAddNamespaceAttribute): Made this a non-member function.
+        (WebCore::MarkupAccumulator::appendNamespace): Fix hash table usage
+        to use add instead of get followed by set to avoid double hashing.
+        Use variadic append to cut down on memory allocation.
+        (WebCore::MarkupAccumulator::appendText): Tweaked style to make this a
+        one-line function.
+        (WebCore::appendComment): Deleted.
+        (WebCore::appendXMLDeclaration): Made this a non-member function.
+        Use variadic append to cut down on memory allocation.
+        (WebCore::appendDocumentType): Made this a non-member function.
+        Use variadic append to cut down on memory allocation.
+        (WebCore::MarkupAccumulator::appendCDATASection): Deleted.
+        (WebCore::MarkupAccumulator::appendNonElementNode): Moved the bodies of
+        appendComment, appendProcessingInstruction, and appendCDATASection in
+        here since they can all be one-line variadic append calls.
+
+        * editing/MarkupAccumulator.h:
+        (WebCore::MarkupAccumulator::length const): Changed the return type
+        of length to be unsigned since that's what StringBuilder returns.
+        Made isAllASCII call StringBuilder::isAllASCII. Replaced appendString
+        and appendStringView with variadic append. Removed many functions
+        that no longer need to be member functions. Made appendAttributeValue
+        a static member function. Made appendNamespace private. Made
+        m_serializationSyntax const.
+
+        * editing/markup.cpp:
+        (WebCore::StyledMarkupAccumulator::wrapWithStyleNode): Use append
+        instead of appenString.
+        (WebCore::StyledMarkupAccumulator::isAllASCII const): Added. Before
+        the code would only check the StringBuilder, but we also need to
+        check m_reversedPrecedingMarkup.
+        (WebCore::StyledMarkupAccumulator::takeResults): Use CheckedUint32
+        since StringBuilder's reserveCapacity function takes unsigned, not
+        size_t. The old code, using totalLength, would just pass a size_t
+        and let it get chopped off, which didn't do any harm, but it seems
+        strange to compute a 64-bit value just to chop off the lower 32
+        bits. An alternative is to compute the 32-bit value and just let
+        it overflow. Use a modern for loop by defining a ReverseView
+        template rather than writing a confusing backwards loop. Use the
+        new takeMarkup instead of concatenateMarkup.
+        (WebCore::StyledMarkupAccumulator::appendText): Tweak coding
+        style a little bit.
+        (WebCore::StyledMarkupAccumulator::appendStartTag): Ditto.
+        (WebCore::StyledMarkupAccumulator::appendNodeToPreserveMSOList):
+        Use variadic append to cut down on memory allocations.
+        (WebCore::propertyMissingOrEqualToNone): Tweak coding style a bit.
+        (WebCore::serializePreservingVisualAppearanceInternal): Use
+        append instead of appendString.
+        (WebCore::shouldPreserveMSOLists): Take a StringView instead of a
+        String to eliminate unnecessary memory allocation in call to substring.
+        (WebCore::sanitizedMarkupForFragmentInDocument): Use makeString
+        instead of StringBuilder to cut down on memory allocation.
+
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::resetDefaultButton): Fix spelling error
+        in the word "explicitly".
+        * mathml/MathMLOperatorDictionary.cpp:
+        (WebCore::MathMLOperatorDictionary::search): Ditto.
+
+        * page/PageSerializer.cpp:
+        (WebCore::PageSerializer::SerializerMarkupAccumulator::SerializerMarkupAccumulator):
+        Use variadic append instead of appendString to cut down on
+        memory allocations.
+
+        * rendering/svg/SVGInlineTextBox.cpp:
+        (WebCore::SVGInlineTextBox::paint): Fix spelling error in the word
+        "explicitly".
+
 2020-05-09  Jack Lee  <[email protected]>
 
         Nullptr crash in LegacyWebArchive::createPropertyListRepresentation when copying selected range that contains surrogate characters

Modified: trunk/Source/WebCore/editing/MarkupAccumulator.cpp (261436 => 261437)


--- trunk/Source/WebCore/editing/MarkupAccumulator.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/editing/MarkupAccumulator.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -160,11 +160,11 @@
 
 void MarkupAccumulator::appendCharactersReplacingEntities(StringBuilder& result, const String& source, unsigned offset, unsigned length, EntityMask entityMask)
 {
-    if (!(offset + length))
+    ASSERT(offset + length <= source.length());
+
+    if (!length)
         return;
 
-    ASSERT(offset + length <= source.length());
-
     if (source.is8Bit())
         appendCharactersReplacingEntitiesInternal<LChar>(result, source, offset, length, entityMask);
     else
@@ -235,16 +235,6 @@
     return urlString;
 }
 
-void MarkupAccumulator::appendString(const String& string)
-{
-    m_markup.append(string);
-}
-
-void MarkupAccumulator::appendStringView(StringView view)
-{
-    m_markup.append(view);
-}
-
 void MarkupAccumulator::startAppendingNode(const Node& node, Namespaces* namespaces)
 {
     if (is<Element>(node))
@@ -260,25 +250,14 @@
 {
     if (shouldSelfClose(element, m_serializationSyntax) || (!element.hasChildNodes() && elementCannotHaveEndTag(element)))
         return;
-    result.append('<');
-    result.append('/');
-    result.append(element.nodeNamePreservingCase());
-    result.append('>');
+    result.append("</", element.nodeNamePreservingCase(), '>');
 }
 
-size_t MarkupAccumulator::totalLength(const Vector<String>& strings)
+StringBuilder MarkupAccumulator::takeMarkup()
 {
-    size_t length = 0;
-    for (auto& string : strings)
-        length += string.length();
-    return length;
+    return std::exchange(m_markup, { });
 }
 
-void MarkupAccumulator::concatenateMarkup(StringBuilder& result)
-{
-    result.append(m_markup);
-}
-
 void MarkupAccumulator::appendAttributeValue(StringBuilder& result, const String& attribute, bool isSerializingHTML)
 {
     appendCharactersReplacingEntities(result, attribute, 0, attribute.length(),
@@ -293,7 +272,7 @@
 {
     ASSERT(element.isURLAttribute(attribute));
     String resolvedURLString = resolveURLIfNeeded(element, attribute.value());
-    UChar quoteChar = '"';
+    char quoteChar = '"';
     if (WTF::protocolIsJavaScript(resolvedURLString)) {
         // minimal escaping for _javascript_ urls
         if (resolvedURLString.contains('"')) {
@@ -302,9 +281,7 @@
             else
                 quoteChar = '\'';
         }
-        result.append(quoteChar);
-        result.append(resolvedURLString);
-        result.append(quoteChar);
+        result.append(quoteChar, resolvedURLString, quoteChar);
         return;
     }
 
@@ -314,18 +291,16 @@
     result.append(quoteChar);
 }
 
-bool MarkupAccumulator::shouldAddNamespaceElement(const Element& element)
+static bool shouldAddNamespaceElement(const Element& element)
 {
     // Don't add namespace attribute if it is already defined for this elem.
-    const AtomString& prefix = element.prefix();
+    auto& prefix = element.prefix();
     if (prefix.isEmpty())
         return !element.hasAttribute(xmlnsAtom());
-
-    static NeverDestroyed<String> xmlnsWithColon(MAKE_STATIC_STRING_IMPL("xmlns:"));
-    return !element.hasAttribute(xmlnsWithColon.get() + prefix);
+    return !element.hasAttribute("xmlns:" + prefix);
 }
 
-bool MarkupAccumulator::shouldAddNamespaceAttribute(const Attribute& attribute, Namespaces& namespaces)
+static bool shouldAddNamespaceAttribute(const Attribute& attribute, Namespaces& namespaces)
 {
     namespaces.checkConsistency();
 
@@ -356,26 +331,25 @@
         return;
     }
 
-    // Use emptyAtom()s's impl() for both null and empty strings since the HashMap can't handle 0 as a key
-    AtomStringImpl* pre = prefix.isEmpty() ? emptyAtom().impl() : prefix.impl();
-    AtomStringImpl* foundNS = namespaces.get(pre);
-    if (foundNS != namespaceURI.impl()) {
-        namespaces.set(pre, namespaceURI.impl());
-        // Add namespace to prefix pair so we can do constraint checking later.
-        if (inXMLFragmentSerialization() && !prefix.isEmpty())
-            namespaces.set(namespaceURI.impl(), pre);
-        // Make sure xml prefix and namespace are always known to uphold the constraints listed at http://www.w3.org/TR/xml-names11/#xmlReserved.
-        if (namespaceURI.impl() == XMLNames::xmlNamespaceURI->impl())
+    // Use emptyAtom()s's impl() for null strings since this HashMap can't handle nullptr as a key
+    auto addResult = namespaces.add(prefix.isNull() ? emptyAtom().impl() : prefix.impl(), namespaceURI.impl());
+    if (!addResult.isNewEntry) {
+        if (addResult.iterator->value == namespaceURI.impl())
             return;
-        result.append(' ', xmlnsAtom());
-        if (!prefix.isEmpty())
-            result.append(':', prefix);
+        addResult.iterator->value = namespaceURI.impl();
+    }
 
-        result.append('=');
-        result.append('"');
-        appendAttributeValue(result, namespaceURI, false);
-        result.append('"');
-    }
+    // Add namespace to prefix pair so we can do constraint checking later.
+    if (inXMLFragmentSerialization() && !prefix.isEmpty())
+        namespaces.set(namespaceURI.impl(), prefix.impl());
+
+    // Make sure xml prefix and namespace are always known to uphold the constraints listed at http://www.w3.org/TR/xml-names11/#xmlReserved.
+    if (namespaceURI == XMLNames::xmlNamespaceURI)
+        return;
+
+    result.append(' ', xmlnsAtom(), prefix.isEmpty() ? "" : ":", prefix, "=\"");
+    appendAttributeValue(result, namespaceURI, false);
+    result.append('"');
 }
 
 EntityMask MarkupAccumulator::entityMaskForText(const Text& text) const
@@ -394,78 +368,42 @@
 
 void MarkupAccumulator::appendText(StringBuilder& result, const Text& text)
 {
-    const String& textData = text.data();
-    appendCharactersReplacingEntities(result, textData, 0, textData.length(), entityMaskForText(text));
+    appendCharactersReplacingEntities(result, text.data(), 0, text.length(), entityMaskForText(text));
 }
 
-static void appendComment(StringBuilder& result, const String& comment)
+static void appendXMLDeclaration(StringBuilder& result, const Document& document)
 {
-    // FIXME: Comment content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "-->".
-    result.appendLiteral("<!--");
-    result.append(comment);
-    result.appendLiteral("-->");
-}
-
-void MarkupAccumulator::appendXMLDeclaration(StringBuilder& result, const Document& document)
-{
     if (!document.hasXMLDeclaration())
         return;
 
-    result.appendLiteral("<?xml version=\"");
-    result.append(document.xmlVersion());
-    const String& encoding = document.xmlEncoding();
-    if (!encoding.isEmpty()) {
-        result.appendLiteral("\" encoding=\"");
-        result.append(encoding);
-    }
-    if (document.xmlStandaloneStatus() != Document::StandaloneStatus::Unspecified) {
-        result.appendLiteral("\" standalone=\"");
-        if (document.xmlStandalone())
-            result.appendLiteral("yes");
-        else
-            result.appendLiteral("no");
-    }
+    auto encoding = document.xmlEncoding();
+    bool isStandaloneSpecified = document.xmlStandaloneStatus() != Document::StandaloneStatus::Unspecified;
 
-    result.appendLiteral("\"?>");
+    result.append("<?xml version=\"",
+        document.xmlVersion(),
+        encoding.isEmpty() ? "" : "\" encoding=\"",
+        encoding,
+        isStandaloneSpecified ? (document.xmlStandalone() ? "\" standalone=\"yes" : "\" standalone=\"no") : "",
+        "\"?>");
 }
 
-void MarkupAccumulator::appendDocumentType(StringBuilder& result, const DocumentType& documentType)
+static void appendDocumentType(StringBuilder& result, const DocumentType& documentType)
 {
     if (documentType.name().isEmpty())
         return;
 
-    result.appendLiteral("<!DOCTYPE ");
-    result.append(documentType.name());
-    if (!documentType.publicId().isEmpty()) {
-        result.appendLiteral(" PUBLIC \"");
-        result.append(documentType.publicId());
-        result.append('"');
-        if (!documentType.systemId().isEmpty()) {
-            result.append(' ');
-            result.append('"');
-            result.append(documentType.systemId());
-            result.append('"');
-        }
-    } else if (!documentType.systemId().isEmpty()) {
-        result.appendLiteral(" SYSTEM \"");
-        result.append(documentType.systemId());
-        result.append('"');
-    }
-    result.append('>');
+    result.append(
+        "<!DOCTYPE ",
+        documentType.name(),
+        documentType.publicId().isEmpty() ? "" : " PUBLIC \"",
+        documentType.publicId(),
+        documentType.publicId().isEmpty() ? "" : "\"",
+        documentType.systemId().isEmpty() ? "" : (documentType.publicId().isEmpty() ? " SYSTEM \"" : " \""),
+        documentType.systemId(),
+        documentType.systemId().isEmpty() ? ">" : "\">"
+    );
 }
 
-void MarkupAccumulator::appendProcessingInstruction(StringBuilder& result, const String& target, const String& data)
-{
-    // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>".
-    result.append('<');
-    result.append('?');
-    result.append(target);
-    result.append(' ');
-    result.append(data);
-    result.append('?');
-    result.append('>');
-}
-
 void MarkupAccumulator::appendStartTag(StringBuilder& result, const Element& element, Namespaces* namespaces)
 {
     appendOpenTag(result, element, namespaces);
@@ -597,14 +535,6 @@
         appendNamespace(result, effectiveXMLPrefixedName->prefix(), effectiveXMLPrefixedName->namespaceURI(), *namespaces);
 }
 
-void MarkupAccumulator::appendCDATASection(StringBuilder& result, const String& section)
-{
-    // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>".
-    result.appendLiteral("<![CDATA[");
-    result.append(section);
-    result.appendLiteral("]]>");
-}
-
 void MarkupAccumulator::appendNonElementNode(StringBuilder& result, const Node& node, Namespaces* namespaces)
 {
     if (namespaces)
@@ -615,7 +545,8 @@
         appendText(result, downcast<Text>(node));
         break;
     case Node::COMMENT_NODE:
-        appendComment(result, downcast<Comment>(node).data());
+        // FIXME: Comment content is not escaped, but that may be OK because XMLSerializer (and possibly other callers) should raise an exception if it includes "-->".
+        result.append("<!--", downcast<Comment>(node).data(), "-->");
         break;
     case Node::DOCUMENT_NODE:
         appendXMLDeclaration(result, downcast<Document>(node));
@@ -626,13 +557,15 @@
         appendDocumentType(result, downcast<DocumentType>(node));
         break;
     case Node::PROCESSING_INSTRUCTION_NODE:
-        appendProcessingInstruction(result, downcast<ProcessingInstruction>(node).target(), downcast<ProcessingInstruction>(node).data());
+        // FIXME: PI data is not escaped, but XMLSerializer (and possibly other callers) this should raise an exception if it includes "?>".
+        result.append("<?", downcast<ProcessingInstruction>(node).target(), ' ', downcast<ProcessingInstruction>(node).data(), "?>");
         break;
     case Node::ELEMENT_NODE:
         ASSERT_NOT_REACHED();
         break;
     case Node::CDATA_SECTION_NODE:
-        appendCDATASection(result, downcast<CDATASection>(node).data());
+        // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other callers) should raise an exception if it includes "]]>".
+        result.append("<![CDATA[", downcast<CDATASection>(node).data(), "]]>");
         break;
     case Node::ATTRIBUTE_NODE:
         ASSERT_NOT_REACHED();

Modified: trunk/Source/WebCore/editing/MarkupAccumulator.h (261436 => 261437)


--- trunk/Source/WebCore/editing/MarkupAccumulator.h	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/editing/MarkupAccumulator.h	2020-05-09 16:04:01 UTC (rev 261437)
@@ -67,21 +67,15 @@
     static void appendCharactersReplacingEntities(StringBuilder&, const String&, unsigned, unsigned, EntityMask);
 
 protected:
-    static size_t totalLength(const Vector<String>&);
-    size_t length() const { return m_markup.length(); }
-    bool isAllASCII() const { return m_markup.toStringPreserveCapacity().isAllASCII(); }
+    unsigned length() const { return m_markup.length(); }
+    bool isAllASCII() const { return m_markup.isAllASCII(); }
 
-    void concatenateMarkup(StringBuilder&);
+    StringBuilder takeMarkup();
 
-    void appendString(const String&);
-    void appendStringView(StringView);
+    template<typename ...StringTypes> void append(StringTypes&&... strings) { m_markup.append(std::forward<StringTypes>(strings)...); }
 
     void startAppendingNode(const Node&, Namespaces* = nullptr);
-    void endAppendingNode(const Node& node)
-    {
-        if (is<Element>(node))
-            appendEndTag(m_markup, downcast<Element>(node));
-    }
+    void endAppendingNode(const Node&);
 
     virtual void appendStartTag(StringBuilder&, const Element&, Namespaces*);
     virtual void appendEndTag(StringBuilder&, const Element&);
@@ -92,23 +86,16 @@
     void appendCloseTag(StringBuilder&, const Element&);
 
     void appendNonElementNode(StringBuilder&, const Node&, Namespaces*);
-    void appendEndMarkup(StringBuilder&, const Element&);
 
-    void appendAttributeValue(StringBuilder&, const String&, bool isSerializingHTML);
-    void appendNamespace(StringBuilder&, const AtomString& prefix, const AtomString& namespaceURI, Namespaces&, bool allowEmptyDefaultNS = false);
-    void appendXMLDeclaration(StringBuilder&, const Document&);
-    void appendDocumentType(StringBuilder&, const DocumentType&);
-    void appendProcessingInstruction(StringBuilder&, const String& target, const String& data);
+    static void appendAttributeValue(StringBuilder&, const String&, bool isSerializingHTML);
     void appendAttribute(StringBuilder&, const Element&, const Attribute&, Namespaces*);
-    void appendCDATASection(StringBuilder&, const String&);
 
-    bool shouldAddNamespaceElement(const Element&);
-    bool shouldAddNamespaceAttribute(const Attribute&, Namespaces&);
     EntityMask entityMaskForText(const Text&) const;
 
     Vector<Node*>* const m_nodes;
 
 private:
+    void appendNamespace(StringBuilder&, const AtomString& prefix, const AtomString& namespaceURI, Namespaces&, bool allowEmptyDefaultNS = false);
     String resolveURLIfNeeded(const Element&, const String&) const;
     void appendQuotedURLAttributeValue(StringBuilder&, const Element&, const Attribute&);
     void serializeNodesWithNamespaces(Node& targetNode, SerializedNodes, const Namespaces*, Vector<QualifiedName>* tagNamesToSkip);
@@ -118,8 +105,14 @@
 
     StringBuilder m_markup;
     const ResolveURLs m_resolveURLs;
-    SerializationSyntax m_serializationSyntax;
+    const SerializationSyntax m_serializationSyntax;
     unsigned m_prefixLevel { 0 };
 };
 
+inline void MarkupAccumulator::endAppendingNode(const Node& node)
+{
+    if (is<Element>(node))
+        appendEndTag(m_markup, downcast<Element>(node));
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/markup.cpp (261436 => 261437)


--- trunk/Source/WebCore/editing/markup.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/editing/markup.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -86,7 +86,7 @@
 
 using namespace HTMLNames;
 
-static bool propertyMissingOrEqualToNone(StyleProperties*, CSSPropertyID);
+static bool propertyMissingOrEqualToNone(const StyleProperties*, CSSPropertyID);
 
 class AttributeChange {
 public:
@@ -231,7 +231,7 @@
     bool needRelativeStyleWrapper() const { return m_needRelativeStyleWrapper; }
     bool needClearingDiv() const { return m_needClearingDiv; }
 
-    using MarkupAccumulator::appendString;
+    using MarkupAccumulator::append;
 
     ContainerNode* parentNode(Node& node)
     {
@@ -242,13 +242,12 @@
 
     void prependMetaCharsetUTF8TagIfNonASCIICharactersArePresent()
     {
-        if (isAllASCII())
-            return;
-
-        m_reversedPrecedingMarkup.append("<meta charset=\"UTF-8\">"_s);
+        if (!isAllASCII())
+            m_reversedPrecedingMarkup.append("<meta charset=\"UTF-8\">"_s);
     }
 
 private:
+    bool isAllASCII() const;
     void appendStyleNodeOpenTag(StringBuilder&, StyleProperties*, Document&, bool isBlock = false);
     const String& styleNodeCloseTag(bool isBlock = false);
 
@@ -364,7 +363,7 @@
     StringBuilder openTag;
     appendStyleNodeOpenTag(openTag, style, document, isBlock);
     m_reversedPrecedingMarkup.append(openTag.toString());
-    appendString(styleNodeCloseTag(isBlock));
+    append(styleNodeCloseTag(isBlock));
 }
 
 void StyledMarkupAccumulator::appendStyleNodeOpenTag(StringBuilder& out, StyleProperties* style, Document& document, bool isBlock)
@@ -386,17 +385,38 @@
     return isBlock ? divClose : styleSpanClose;
 }
 
+bool StyledMarkupAccumulator::isAllASCII() const
+{
+    for (auto& preceding : m_reversedPrecedingMarkup) {
+        if (!preceding.isAllASCII())
+            return false;
+    }
+    return MarkupAccumulator::isAllASCII();
+}
+
+// Stopgap until C++20 adds std::ranges::reverse_view.
+template<typename Collection> struct ReverseView {
+    Collection& collection;
+    decltype(collection.rbegin()) begin() const { return collection.rbegin(); }
+    decltype(collection.rend()) end() const { return collection.rend(); }
+    decltype(collection.size()) size() const { return collection.size(); }
+    ReverseView(Collection& collection)
+        : collection(collection)
+    {
+    }
+};
+
 String StyledMarkupAccumulator::takeResults()
 {
+    CheckedUint32 length = this->length();
+    for (auto& string : m_reversedPrecedingMarkup)
+        length += string.length();
     StringBuilder result;
-    result.reserveCapacity(totalLength(m_reversedPrecedingMarkup) + length());
-
-    for (size_t i = m_reversedPrecedingMarkup.size(); i > 0; --i)
-        result.append(m_reversedPrecedingMarkup[i - 1]);
-
-    concatenateMarkup(result);
-
-    // We remove '\0' characters because they are not visibly rendered to the user.
+    result.reserveCapacity(length.unsafeGet());
+    for (auto& string : ReverseView { m_reversedPrecedingMarkup })
+        result.append(string);
+    result.append(takeMarkup());
+    // Remove '\0' characters because they are not visibly rendered to the user.
     return result.toString().replaceWithLiteral('\0', "");
 }
 
@@ -405,7 +425,7 @@
     const bool parentIsTextarea = is<HTMLTextAreaElement>(text.parentElement());
     const bool wrappingSpan = shouldApplyWrappingStyle(text) && !parentIsTextarea;
     if (wrappingSpan) {
-        RefPtr<EditingStyle> wrappingStyle = m_wrappingStyle->copy();
+        auto wrappingStyle = m_wrappingStyle->copy();
         // FIXME: <rdar://problem/5371536> Style rules that match pasted content can change it's appearance
         // Make sure spans are inline style in paste side e.g. span { display: block }.
         wrappingStyle->forceInline();
@@ -564,7 +584,7 @@
         if (!newInlineStyle->isEmpty()) {
             out.appendLiteral(" style=\"");
             appendAttributeValue(out, newInlineStyle->style()->asText(), documentIsHTML);
-            out.append('\"');
+            out.append('"');
         }
     }
 
@@ -721,9 +741,9 @@
         if (msoListDefinitionsEnd == notFound || start >= msoListDefinitionsEnd)
             return false;
 
-        appendString("<head><style class=\"" WebKitMSOListQuirksStyle "\">\n<!--\n");
-        appendStringView(StringView(textChild.data()).substring(start, msoListDefinitionsEnd - start + 3));
-        appendString("\n-->\n</style></head>");
+        append("<head><style class=\"" WebKitMSOListQuirksStyle "\">\n<!--\n",
+            StringView(textChild.data()).substring(start, msoListDefinitionsEnd - start + 3),
+            "\n-->\n</style></head>");
 
         return true;
     }
@@ -754,16 +774,12 @@
     return ancestorToRetainStructureAndAppearanceForBlock(enclosingBlock(commonAncestor));
 }
 
-static bool propertyMissingOrEqualToNone(StyleProperties* style, CSSPropertyID propertyID)
+static bool propertyMissingOrEqualToNone(const StyleProperties* style, CSSPropertyID propertyID)
 {
     if (!style)
         return false;
-    RefPtr<CSSValue> value = style->getPropertyCSSValue(propertyID);
-    if (!value)
-        return true;
-    if (!is<CSSPrimitiveValue>(*value))
-        return false;
-    return downcast<CSSPrimitiveValue>(*value).valueID() == CSSValueNone;
+    auto value = style->getPropertyCSSValue(propertyID);
+    return !value || (is<CSSPrimitiveValue>(*value) && downcast<CSSPrimitiveValue>(*value).valueID() == CSSValueNone);
 }
 
 static bool needInterchangeNewlineAfter(const VisiblePosition& v)
@@ -869,7 +885,7 @@
         if (visibleStart == visibleEnd.previous())
             return interchangeNewlineString;
 
-        accumulator.appendString(interchangeNewlineString);
+        accumulator.append(interchangeNewlineString.get());
         startAdjustedForInterchangeNewline = visibleStart.next().deepEquivalent();
 
         if (comparePositions(startAdjustedForInterchangeNewline, end) >= 0)
@@ -915,7 +931,7 @@
     
     if (accumulator.needRelativeStyleWrapper() && needsPositionStyleConversion) {
         if (accumulator.needClearingDiv())
-            accumulator.appendString("<div style=\"clear: both;\"></div>");
+            accumulator.append("<div style=\"clear: both;\"></div>");
         RefPtr<EditingStyle> positionRelativeStyle = styleFromMatchedRulesAndInlineDecl(*body);
         positionRelativeStyle->style()->setProperty(CSSPropertyPosition, CSSValueRelative);
         accumulator.wrapWithStyleNode(positionRelativeStyle->style(), document, true);
@@ -923,7 +939,7 @@
 
     // FIXME: The interchange newline should be placed in the block that it's in, not after all of the content, unconditionally.
     if (annotate == AnnotateForInterchange::Yes && needInterchangeNewlineAfter(visibleEnd.previous()))
-        accumulator.appendString(interchangeNewlineString);
+        accumulator.append(interchangeNewlineString.get());
 
 #if PLATFORM(COCOA)
     // On Cocoa platforms, this markup is eventually persisted to the pasteboard and read back as UTF-8 data,
@@ -930,6 +946,7 @@
     // so this meta tag is needed for clients that read this data in the future from the pasteboard and load it.
     accumulator.prependMetaCharsetUTF8TagIfNonASCIICharactersArePresent();
 #endif
+
     return accumulator.takeResults();
 }
 
@@ -945,8 +962,7 @@
         AnnotateForInterchange::Yes, ConvertBlocksToInlines::No, StandardFontFamilySerializationMode::Keep, MSOListMode::DoNotPreserve);
 }
 
-
-static bool shouldPreserveMSOLists(const String& markup)
+static bool shouldPreserveMSOLists(StringView markup)
 {
     if (!markup.startsWith("<html xmlns:"))
         return false;
@@ -953,9 +969,9 @@
     auto tagClose = markup.find('>');
     if (tagClose == notFound)
         return false;
-    auto htmlTag = markup.substring(0, tagClose);
-    return htmlTag.contains("xmlns:o=\"urn:schemas-microsoft-com:office:office\"")
-        && htmlTag.contains("xmlns:w=\"urn:schemas-microsoft-com:office:word\"");
+    auto tag = markup.substring(0, tagClose);
+    return tag.contains("xmlns:o=\"urn:schemas-microsoft-com:office:office\"")
+        && tag.contains("xmlns:w=\"urn:schemas-microsoft-com:office:word\"");
 }
 
 String sanitizedMarkupForFragmentInDocument(Ref<DocumentFragment>&& fragment, Document& document, MSOListQuirks msoListQuirks, const String& originalMarkup)
@@ -971,20 +987,16 @@
     auto result = serializePreservingVisualAppearanceInternal(firstPositionInNode(bodyElement.get()), lastPositionInNode(bodyElement.get()), nullptr,
         ResolveURLs::YesExcludingLocalFileURLsForPrivacy, SerializeComposedTree::No, AnnotateForInterchange::Yes, ConvertBlocksToInlines::No,  StandardFontFamilySerializationMode::Strip, msoListMode);
 
-    StringBuilder builder;
-    if (msoListMode == MSOListMode::Preserve) {
-        builder.appendLiteral("<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"\n"
-            "xmlns:w=\"urn:schemas-microsoft-com:office:word\"\n"
-            "xmlns:m=\"http://schemas.microsoft.com/office/2004/12/omml\"\n"
-            "xmlns=\"http://www.w3.org/TR/REC-html40\">");
-    }
+    if (msoListMode != MSOListMode::Preserve)
+        return result;
 
-    builder.append(result);
-
-    if (msoListMode == MSOListMode::Preserve)
-        builder.appendLiteral("</html>");
-
-    return builder.toString();
+    return makeString(
+        "<html xmlns:o=\"urn:schemas-microsoft-com:office:office\"\n"
+        "xmlns:w=\"urn:schemas-microsoft-com:office:word\"\n"
+        "xmlns:m=\"http://schemas.microsoft.com/office/2004/12/omml\"\n"
+        "xmlns=\"http://www.w3.org/TR/REC-html40\">",
+        result,
+        "</html>");
 }
 
 static void restoreAttachmentElementsInFragment(DocumentFragment& fragment)

Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (261436 => 261437)


--- trunk/Source/WebCore/html/HTMLFormElement.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -714,7 +714,7 @@
     if (!m_defaultButton) {
         // Computing the default button is not cheap, we don't want to do it unless needed.
         // If there was no default button set, the only style to invalidate is the element
-        // being added to the form. This is done explicitely in registerFormElement().
+        // being added to the form. This is done explicitly in registerFormElement().
         return;
     }
 

Modified: trunk/Source/WebCore/mathml/MathMLOperatorDictionary.cpp (261436 => 261437)


--- trunk/Source/WebCore/mathml/MathMLOperatorDictionary.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/mathml/MathMLOperatorDictionary.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -1138,7 +1138,7 @@
     if (explicitForm)
         return WTF::nullopt;
 
-    // If we did not find the desired operator form and if it was not set explicitely, we use the first one in the following order: Infix, Prefix, Postfix.
+    // If we did not find the desired operator form and if it was not set explicitly, we use the first one in the following order: Infix, Prefix, Postfix.
     // This is to handle bad MathML markup without explicit <mrow> delimiters like "<mo>(</mo><mi>a</mi><mo>)</mo><mo>(</mo><mi>b</mi><mo>)</mo>" where innerfences should not be considered infix.
     if (auto* entry = tryBinarySearch<const Entry, UChar32>(dictionary, dictionarySize, character, ExtractChar)) {
         // There are at most two other entries before the one found.

Modified: trunk/Source/WebCore/page/PageSerializer.cpp (261436 => 261437)


--- trunk/Source/WebCore/page/PageSerializer.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/page/PageSerializer.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -113,9 +113,9 @@
     , m_serializer(serializer)
     , m_document(document)
 {
-    // MarkupAccumulator does not serialize the <?xml ... line, so we add it explicitely to ensure the right encoding is specified.
+    // MarkupAccumulator does not serialize the <?xml ... line, so we add it explicitly to ensure the right encoding is specified.
     if (m_document.isXMLDocument() || m_document.xmlStandalone())
-        appendString("<?xml version=\"" + m_document.xmlVersion() + "\" encoding=\"" + m_document.charset() + "\"?>");
+        append("<?xml version=\"", m_document.xmlVersion(), "\" encoding=\"", m_document.charset(), "\"?>");
 }
 
 void PageSerializer::SerializerMarkupAccumulator::appendText(StringBuilder& out, const Text& text)

Modified: trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp (261436 => 261437)


--- trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Source/WebCore/rendering/svg/SVGInlineTextBox.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -240,7 +240,7 @@
     if (renderer().style().visibility() != Visibility::Visible)
         return;
 
-    // Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
+    // Note: We're explicitly not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
     // If we ever need that for SVG, it's very easy to refactor and reuse the code.
 
     auto& parentRenderer = parent()->renderer();

Modified: trunk/Tools/ChangeLog (261436 => 261437)


--- trunk/Tools/ChangeLog	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Tools/ChangeLog	2020-05-09 16:04:01 UTC (rev 261437)
@@ -1,3 +1,13 @@
+2020-05-08  Darin Adler  <[email protected]>
+
+        Streamline MarkupAccumulator to improve efficiency a bit
+        https://bugs.webkit.org/show_bug.cgi?id=211656
+
+        Reviewed by Anders Carlsson.
+
+        * TestWebKitAPI/Tests/WTF/StringImpl.cpp:
+        (TestWebKitAPI::TEST): Fix spellling error in the word "explicitly".
+
 2020-05-08  David Kilzer  <[email protected]>
 
         Remove empty directories from from svn.webkit.org repository

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp (261436 => 261437)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp	2020-05-09 16:02:26 UTC (rev 261436)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp	2020-05-09 16:04:01 UTC (rev 261437)
@@ -41,7 +41,7 @@
     ASSERT_TRUE(equal(stringWithTemplate.get(), "Template Literal"));
     ASSERT_TRUE(stringWithTemplate->is8Bit());
 
-    // Constructor taking the size explicitely.
+    // Constructor taking the size explicitly.
     const char* programmaticStringData = "Explicit Size Literal";
     auto programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData));
     ASSERT_EQ(strlen(programmaticStringData), programmaticString->length());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to