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());