Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce fast path for innerHTML #9926

Merged

Conversation

cdumez
Copy link
Contributor

@cdumez cdumez commented Feb 10, 2023

236ad6c

Introduce fast path for innerHTML
https://bugs.webkit.org/show_bug.cgi?id=252054

Reviewed by Darin Adler.

This patch imports the new fast HTML parser from Blink:
https://bugs.chromium.org/p/chromium/issues/detail?id=1407201

This patch adds a new parser that handles a subset of HTML and is only used by
Element::set[Inner|Outer]HTML. While limited, the hope is this parser is
useful for a number of pages. We could expand on the set of cases this handles
in the future.

As a sanity check, there is a debug assertion in place to make sure that the
fast path generates the same output as the full HTML parser would have.

This is a verified 2.25% progression on Speedometer on macOS and 2.60%
progression on iOS.

* Source/WTF/wtf/text/WTFString.h:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.h:
(WebCore::Document::isDirAttributeDirty const):
(WebCore::Document::setIsDirAttributeDirty):
(WebCore::Document::isTemplateDocument const):
* Source/WebCore/editing/markup.cpp:
(WebCore::createFragmentForMarkup):
* Source/WebCore/html/HTMLBDIElement.cpp:
(WebCore::HTMLBDIElement::HTMLBDIElement):
* Source/WebCore/html/HTMLButtonElement.cpp:
(WebCore::HTMLButtonElement::create):
* Source/WebCore/html/HTMLButtonElement.h:
* Source/WebCore/html/HTMLElement.cpp:
(WebCore::HTMLElement::childrenChanged):
(WebCore::HTMLElement::dirAttributeChanged):

* Source/WebCore/html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::~HTMLInputElement):
(WebCore::HTMLInputElement::needsSuspensionCallback):
We have an optimization in HTMLInputElement which delays the initialization of
m_inputType when constructed by the HTML parser. However, in the fast-parsing
case, we may now fail parsing (due to limited support) in the middle of parsing
an HTMLInputElement. As a result, we may end up destroying an HTMLInputElement
before its m_inputType gets initialized, which would cause a crash. I added a
couple of null checks for m_inputType so that the HTMLInputElement destructor
can run even if m_inputType wasn't initialized yet.

* Source/WebCore/html/HTMLLabelElement.cpp:
(WebCore::HTMLLabelElement::create):
* Source/WebCore/html/HTMLLabelElement.h:
* Source/WebCore/html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::create):
* Source/WebCore/html/HTMLSelectElement.h:
* Source/WebCore/html/parser/HTMLDocumentParserFastPath.cpp: Added.
(WebCore::operator==):
(WebCore::onlyContainsLowercaseASCIILetters):
(WebCore::tagNameHash):
(WebCore::HTMLFastPathParser::HTMLFastPathParser):
(WebCore::HTMLFastPathParser::parse):
(WebCore::HTMLFastPathParser::parseResult const):
(WebCore::HTMLFastPathParser::TagInfo::Tag::create):
(WebCore::HTMLFastPathParser::TagInfo::Tag::allowedInPhrasingOrFlowContent):
(WebCore::HTMLFastPathParser::TagInfo::Tag::allowedInFlowContent):
(WebCore::HTMLFastPathParser::TagInfo::ContainerTag::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::ContainsPhrasingContentTag::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::A::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::AWithPhrasingContent::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::B::create):
(WebCore::HTMLFastPathParser::TagInfo::Footer::create):
(WebCore::HTMLFastPathParser::TagInfo::I::create):
(WebCore::HTMLFastPathParser::TagInfo::Input::create):
(WebCore::HTMLFastPathParser::TagInfo::Option::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::Ol::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::Select::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::Strong::create):
(WebCore::HTMLFastPathParser::TagInfo::Ul::parseChild):
(WebCore::HTMLFastPathParser::parseCompleteInput):
(WebCore::HTMLFastPathParser::isWhitespace):
(WebCore::HTMLFastPathParser::isValidUnquotedAttributeValueChar):
(WebCore::HTMLFastPathParser::isValidAttributeNameChar):
(WebCore::HTMLFastPathParser::isCharAfterTagNameOrAttribute):
(WebCore::HTMLFastPathParser::isCharAfterUnquotedAttribute):
(WebCore::HTMLFastPathParser::skipWhitespace):
(WebCore::HTMLFastPathParser::scanText):
(WebCore::HTMLFastPathParser::scanEscapedText):
(WebCore::HTMLFastPathParser::scanTagName):
(WebCore::HTMLFastPathParser::scanAttributeName):
(WebCore::HTMLFastPathParser::scanAttributeValue):
(WebCore::HTMLFastPathParser::scanEscapedAttributeValue):
(WebCore::HTMLFastPathParser::scanHTMLCharacterReference):
(WebCore::HTMLFastPathParser::didFail):
(WebCore::HTMLFastPathParser::peekNext):
(WebCore::HTMLFastPathParser::consumeNext):
(WebCore::HTMLFastPathParser::parseChildren):
(WebCore::HTMLFastPathParser::processAttribute):
(WebCore::HTMLFastPathParser::parseAttributes):
(WebCore::HTMLFastPathParser::parseSpecificElements):
(WebCore::HTMLFastPathParser::parseElement):
(WebCore::HTMLFastPathParser::parseElementAfterTagName):
(WebCore::HTMLFastPathParser::parseContainerElement):
(WebCore::HTMLFastPathParser::parseVoidElement):
(WebCore::canUseFastPath):
(WebCore::tryFastParsingHTMLFragmentImpl):
(WebCore::tryFastParsingHTMLFragment):
* Source/WebCore/html/parser/HTMLDocumentParserFastPath.h: Added.
* Source/WebCore/html/parser/HTMLEntityParser.cpp:
(WebCore::appendLegalEntityFor):
* Source/WebCore/html/parser/HTMLEntityParser.h:
* Source/WebCore/html/parser/HTMLNameCache.h:
(WebCore::HTMLNameCache::makeAttributeQualifiedName):
(WebCore::HTMLNameCache::makeQualifiedName):

Canonical link: https://commits.webkit.org/260148@main

ba5d5d4

Misc iOS, tvOS & watchOS macOS Linux Windows
❌ πŸ§ͺ style βœ… πŸ›  ios βœ… πŸ›  mac βœ… πŸ›  wpe   πŸ›  wincairo
βœ… πŸ§ͺ bindings βœ… πŸ›  ios-sim βœ… πŸ›  mac-AS-debug βœ… πŸ›  gtk
βœ… πŸ§ͺ webkitperl   πŸ§ͺ ios-wk2 βœ… πŸ§ͺ api-mac   πŸ§ͺ gtk-wk2
βœ… πŸ§ͺ api-ios   πŸ§ͺ mac-wk1   πŸ§ͺ api-gtk
βœ… πŸ›  πŸ§ͺ jsc βœ… πŸ›  tv βœ… πŸ§ͺ mac-wk2   πŸ›  jsc-armv7
βœ… πŸ›  πŸ§ͺ jsc-arm64 βœ… πŸ›  tv-sim   πŸ§ͺ mac-AS-debug-wk2   πŸ§ͺ jsc-armv7-tests
βœ… πŸ›  watch βœ… πŸ§ͺ mac-wk2-stress βœ… πŸ›  jsc-mips
βœ… πŸ›  πŸ§ͺ merge βœ… πŸ›  watch-sim βœ… πŸ§ͺ jsc-mips-tests

@cdumez cdumez self-assigned this Feb 10, 2023
@cdumez cdumez added the WebCore Misc. For miscellaneous bugs in the WebCore framework (and not JavaScriptCore or WebKit). label Feb 10, 2023
@weinig
Copy link
Contributor

weinig commented Feb 10, 2023

What makes the fast path parser faster? For instance, the fast path CSS property parser skips tokenization and just tries to match certain character sequences directly.

@@ -104,6 +104,8 @@ class String final {
unsigned length() const { return m_impl ? m_impl->length() : 0; }
const LChar* characters8() const { return m_impl ? m_impl->characters8() : nullptr; }
const UChar* characters16() const { return m_impl ? m_impl->characters16() : nullptr; }
Span<const LChar> span8() const { return { characters8(), length() }; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda feel like these should have the characters8/16 name long term and the raw pointers one can either go away or have a longer name. Not worth changing in this patch, but maybe worth a comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to be consistent with StringView which already had those:

    const LChar* characters8() const;
    const UChar* characters16() const;
    Span<const LChar> span8() const { return { characters8(), length() }; }
    Span<const UChar> span16() const { return { characters16(), length() }; }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future consideration, I like Sam’s idea even though I am the one who named the functions in StringView.

@cdumez
Copy link
Contributor Author

cdumez commented Feb 10, 2023

What makes the fast path parser faster? For instance, the fast path CSS property parser skips tokenization and just tries to match certain character sequences directly.

I didn't write it. I imported it from Blink and perf-tested it.

I believe the fact that it only deals with a very small subset of HTML makes it faster.

I am still A/B testings some things to see if we can make it even faster but I decided to upload this patch already since it already tested as a very good progression and passes all the tests.

Document& m_document;
DocumentFragment& m_fragment;

const Char* const m_end { m_source.data() + m_source.size() };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider using an abstraction like the StringParsingBuffer rather than raw pointers?

Copy link
Contributor Author

@cdumez cdumez Feb 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a straight import. I didn't make any tweaks yet. I think we should adopt more WebKit concepts, though I was hoping to do it in a follow-up since each change will have to be perf-tested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give it a shot in a follow-up and perf test it. I would be nicer than dealing with pointers indeed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to rewrite the code using StringParsingBuffer easily. I am waiting on A/B perf results.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a small regression at the moment, I am trying to figure out why.

@cdumez cdumez marked this pull request as ready for review February 11, 2023 00:45
@cdumez cdumez requested a review from rniwa as a code owner February 11, 2023 00:45
Copy link
Member

@darinadler darinadler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So many coding style tweaks possibilities, and maybe additional optimization too. But it’s great to get this in here.

@@ -104,6 +104,8 @@ class String final {
unsigned length() const { return m_impl ? m_impl->length() : 0; }
const LChar* characters8() const { return m_impl ? m_impl->characters8() : nullptr; }
const UChar* characters16() const { return m_impl ? m_impl->characters16() : nullptr; }
Span<const LChar> span8() const { return { characters8(), length() }; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future consideration, I like Sam’s idea even though I am the one who named the functions in StringView.

Comment on lines +1349 to +1358
bool parsedUsingFastPath = tryFastParsingHTMLFragment(markup, document, fragment, contextElement, parserContentPolicy);
if (parsedUsingFastPath) {
#if ASSERT_ENABLED
// As a sanity check for the fast-path, create another fragment using the full parser and compare the results.
auto referenceFragment = DocumentFragment::create(document);
referenceFragment->parseHTML(markup, &contextElement, parserContentPolicy);
ASSERT(serializeFragment(fragment, SerializedNodes::SubtreesOfChildren) == serializeFragment(referenceFragment, SerializedNodes::SubtreesOfChildren));
#endif
} else
fragment->parseHTML(markup, &contextElement, parserContentPolicy);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this all go into the fragment->parseHTML function, not here? The abstraction is "faster way to parse", not "two different ways to parse", so I think one level deeper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the fast path can start parsing and populating the fragment, then encounter something it can't parse and give up. When it gives up we currently destroy the fragment and reconstruct a new one before calling fragment->parseHTML(). This reconstruction makes what you suggest not possible so we'd need another approach. I already tried calling removeChildren() on the fragment but that turned out to be too expensive. I need to find a cheaper way.

Comment on lines +1490 to +1491
if (!m_inputType)
return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this change for? Change log doesn’t say.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@@ -141,7 +141,7 @@ HTMLInputElement::~HTMLInputElement()
// a radio button that was in a form. The call to setForm(nullptr) above
// actually adds the button to the document groups in the latter case.
// That is inelegant, but harmless since we remove it here.
if (isRadioButton())
if (m_inputType && isRadioButton())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for? Change log doesn’t say.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add in the commit log. A while back, we landed a Speedometer optimization in HTMLInputElement which delays initialization of the inputType when constructed by the parser. This was to avoid creating an inputType for "text" only to figure out later during parsing that we wanted another type.

There is a case in the new HTML fast parsing case where we give up parsing a destroy a newly constructed HTMLInputElement before we're done fully parsing it. As a result, the input element may now get destroyed before its m_inputType got initialized. However, the HTMLInputElement would previously crash if m_inputType is null. It seemed like a waste to force the initialization of m_inputType in this case so I decided to go the other way and add support for an HTMLInputElement to get destroyed before its m_inputType gets initialized.

FailedMaxDepth,
FailedBigText,
FailedCssPseudoDirEnabledAndDirAttributeDirty,
MaxValue = FailedCssPseudoDirEnabledAndDirAttributeDirty,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should leave this MaxValue thing out since it’s never used.

@@ -146,4 +146,9 @@ size_t decodeNamedEntityToUCharArray(const char* name, UChar result[4])
return numberOfCodePoints + appendUChar32ToUCharArray(search.mostRecentMatch()->secondValue, result + numberOfCodePoints);
}

void appendLegalEntityFor(UChar32 c, StringBuilder& decodedEntity)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the name character rather than c.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

Is it because it is a UChar32?

You didn't make the same comment for the other functions taking a c so I started wondering.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just ran out of steam reviewing, really. I think occasionally a single letter name could be justified but in a short function I think we’d want to used a word instead of a letter.

Comment on lines 746 to 749
StringBuilder entity;
appendLegalEntityFor(res, entity);
for (unsigned i = 0; i < entity.length(); ++i)
out.append(entity[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems inefficient. Why not just have appendLegalEntityFor take a Vector<UChar>? Making and destroying a string each time won’t be fast.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good point! I'll make this change. I only used StringBuilder for consistency with the other API in that header but didn't think enough about the performance implications.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Planning on going with:

void appendLegalEntityFor(UChar32 c, Vector<UChar>& decodedEntity)
{
    auto legalEntity = HTMLEntityParser::legalEntityFor(c);
    if (U_IS_BMP(legalEntity)) {
        decodedEntity.append(static_cast<UChar>(legalEntity));
        return;
    }
    decodedEntity.append(U16_LEAD(legalEntity));
    decodedEntity.append(U16_TRAIL(legalEntity));
}

Comment on lines 33 to 34
bool consumeHTMLEntity(SegmentedString&, StringBuilder& decodedEntity, bool& notEnoughCharacters, UChar additionalAllowedCharacter = '\0');
void appendLegalEntityFor(UChar32, StringBuilder& decodedEntity);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name decodedEntity is not a good name for a StringBuilder that we will be appending to. Sure, the thing we are appending is a decoded entity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Proposing ouputBuffer

m_parsingFailed = true;
}

template<class ResultType> ResultType didFail(HTMLFastPathResult result, ResultType res)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These argument names: result and res, not very helpful. I suggest returnValue instead of res.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will use ResultType -> ReturnValueType for the template parameter as well, to avoid confusion.

Comment on lines +898 to +881
std::sort(m_attributeNames.begin(), m_attributeNames.end());
if (std::adjacent_find(m_attributeNames.begin(), m_attributeNames.end()) != m_attributeNames.end()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is sorting really the fastest way to find duplicates? Seems unlikely. I think a HashSet<AtomString> would be faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I'll add a FIXME comment for now and evaluate this in a follow-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, interestingly, switching to a HashSet appears to be a confirmed 0.8% regression on Speedometer on iOS.
My bet at the moment is that the issue with the HashSet is that it we don't have a way to clear it while retaining its internal capacity. Unlike a Vector where you can resize(0) and drop its items while retaining its capacity. This is helpful since the parser currently reuses the same parser between elements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we have varieties of HashSet including ones with minimum capacity so we don't spend so much time reallocating memory. If the regression really about the memory allocation and not the hashing I think we can fix it. But maybe this is already fast enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I guess all of them lack a clear function that clears in place. I do think a version that only grows and never shrinks could be useful in many places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am A/B testing a version with a HashSet that doesn't clear capacity so see if it is faster. If not, I guess the cost would be the hashing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the version that uses a HashSet and clears it while maintaining its capacity is perf-neutral. It's a little disappointing.
We may still want to do it since a HashSet would be less prone to pathological cases than vector sorting & deduping.

// Used if the attribute name contains upper case ascii (which must be mapped to lower case).
// 32 matches that used by HTMLToken::Attribute.
Vector<Char, 32> m_attributeNameBuffer;
Vector<Attribute> m_attributeBuffer;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this vector is a big contributor to fastMalloc() in the profiles. I think ideally we'd use Vector<Attribute, 10> like we do in the full HTML parser. However, this requires some code changes to make it build/work. I am currently A/B testing such change.

@cdumez cdumez added the merge-queue Applied to send a pull request to merge-queue label Feb 11, 2023
https://bugs.webkit.org/show_bug.cgi?id=252054

Reviewed by Darin Adler.

This patch imports the new fast HTML parser from Blink:
https://bugs.chromium.org/p/chromium/issues/detail?id=1407201

This patch adds a new parser that handles a subset of HTML and is only used by
Element::set[Inner|Outer]HTML. While limited, the hope is this parser is
useful for a number of pages. We could expand on the set of cases this handles
in the future.

As a sanity check, there is a debug assertion in place to make sure that the
fast path generates the same output as the full HTML parser would have.

This is a verified 2.25% progression on Speedometer on macOS and 2.60%
progression on iOS.

* Source/WTF/wtf/text/WTFString.h:
* Source/WebCore/Sources.txt:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/dom/Document.h:
(WebCore::Document::isDirAttributeDirty const):
(WebCore::Document::setIsDirAttributeDirty):
(WebCore::Document::isTemplateDocument const):
* Source/WebCore/editing/markup.cpp:
(WebCore::createFragmentForMarkup):
* Source/WebCore/html/HTMLBDIElement.cpp:
(WebCore::HTMLBDIElement::HTMLBDIElement):
* Source/WebCore/html/HTMLButtonElement.cpp:
(WebCore::HTMLButtonElement::create):
* Source/WebCore/html/HTMLButtonElement.h:
* Source/WebCore/html/HTMLElement.cpp:
(WebCore::HTMLElement::childrenChanged):
(WebCore::HTMLElement::dirAttributeChanged):

* Source/WebCore/html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::~HTMLInputElement):
(WebCore::HTMLInputElement::needsSuspensionCallback):
We have an optimization in HTMLInputElement which delays the initialization of
m_inputType when constructed by the HTML parser. However, in the fast-parsing
case, we may now fail parsing (due to limited support) in the middle of parsing
an HTMLInputElement. As a result, we may end up destroying an HTMLInputElement
before its m_inputType gets initialized, which would cause a crash. I added a
couple of null checks for m_inputType so that the HTMLInputElement destructor
can run even if m_inputType wasn't initialized yet.

* Source/WebCore/html/HTMLLabelElement.cpp:
(WebCore::HTMLLabelElement::create):
* Source/WebCore/html/HTMLLabelElement.h:
* Source/WebCore/html/HTMLSelectElement.cpp:
(WebCore::HTMLSelectElement::create):
* Source/WebCore/html/HTMLSelectElement.h:
* Source/WebCore/html/parser/HTMLDocumentParserFastPath.cpp: Added.
(WebCore::operator==):
(WebCore::onlyContainsLowercaseASCIILetters):
(WebCore::tagNameHash):
(WebCore::HTMLFastPathParser::HTMLFastPathParser):
(WebCore::HTMLFastPathParser::parse):
(WebCore::HTMLFastPathParser::parseResult const):
(WebCore::HTMLFastPathParser::TagInfo::Tag::create):
(WebCore::HTMLFastPathParser::TagInfo::Tag::allowedInPhrasingOrFlowContent):
(WebCore::HTMLFastPathParser::TagInfo::Tag::allowedInFlowContent):
(WebCore::HTMLFastPathParser::TagInfo::ContainerTag::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::ContainsPhrasingContentTag::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::A::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::AWithPhrasingContent::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::B::create):
(WebCore::HTMLFastPathParser::TagInfo::Footer::create):
(WebCore::HTMLFastPathParser::TagInfo::I::create):
(WebCore::HTMLFastPathParser::TagInfo::Input::create):
(WebCore::HTMLFastPathParser::TagInfo::Option::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::Ol::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::Select::parseChild):
(WebCore::HTMLFastPathParser::TagInfo::Strong::create):
(WebCore::HTMLFastPathParser::TagInfo::Ul::parseChild):
(WebCore::HTMLFastPathParser::parseCompleteInput):
(WebCore::HTMLFastPathParser::isWhitespace):
(WebCore::HTMLFastPathParser::isValidUnquotedAttributeValueChar):
(WebCore::HTMLFastPathParser::isValidAttributeNameChar):
(WebCore::HTMLFastPathParser::isCharAfterTagNameOrAttribute):
(WebCore::HTMLFastPathParser::isCharAfterUnquotedAttribute):
(WebCore::HTMLFastPathParser::skipWhitespace):
(WebCore::HTMLFastPathParser::scanText):
(WebCore::HTMLFastPathParser::scanEscapedText):
(WebCore::HTMLFastPathParser::scanTagName):
(WebCore::HTMLFastPathParser::scanAttributeName):
(WebCore::HTMLFastPathParser::scanAttributeValue):
(WebCore::HTMLFastPathParser::scanEscapedAttributeValue):
(WebCore::HTMLFastPathParser::scanHTMLCharacterReference):
(WebCore::HTMLFastPathParser::didFail):
(WebCore::HTMLFastPathParser::peekNext):
(WebCore::HTMLFastPathParser::consumeNext):
(WebCore::HTMLFastPathParser::parseChildren):
(WebCore::HTMLFastPathParser::processAttribute):
(WebCore::HTMLFastPathParser::parseAttributes):
(WebCore::HTMLFastPathParser::parseSpecificElements):
(WebCore::HTMLFastPathParser::parseElement):
(WebCore::HTMLFastPathParser::parseElementAfterTagName):
(WebCore::HTMLFastPathParser::parseContainerElement):
(WebCore::HTMLFastPathParser::parseVoidElement):
(WebCore::canUseFastPath):
(WebCore::tryFastParsingHTMLFragmentImpl):
(WebCore::tryFastParsingHTMLFragment):
* Source/WebCore/html/parser/HTMLDocumentParserFastPath.h: Added.
* Source/WebCore/html/parser/HTMLEntityParser.cpp:
(WebCore::appendLegalEntityFor):
* Source/WebCore/html/parser/HTMLEntityParser.h:
* Source/WebCore/html/parser/HTMLNameCache.h:
(WebCore::HTMLNameCache::makeAttributeQualifiedName):
(WebCore::HTMLNameCache::makeQualifiedName):

Canonical link: https://commits.webkit.org/260148@main
@webkit-commit-queue
Copy link
Collaborator

Committed 260148@main (236ad6c): https://commits.webkit.org/260148@main

Reviewed commits have been landed. Closing PR #9926 and removing active labels.

@webkit-early-warning-system webkit-early-warning-system merged commit 236ad6c into WebKit:main Feb 11, 2023
@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Feb 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WebCore Misc. For miscellaneous bugs in the WebCore framework (and not JavaScriptCore or WebKit).
Projects
None yet
5 participants