Repository navigation
Out of order streaming using <template for> - #73326
hjanuschka wants to merge 1 commit into
Conversation
|
EWS run on previous version of this PR (hash 4ed38d8) Details |
4ed38d8 to
4c8d94e
Compare
|
EWS run on previous version of this PR (hash 4c8d94e) Details |
4c8d94e to
4ee52fc
Compare
|
EWS run on previous version of this PR (hash 4ee52fc) Details |
|
@hjanuschka - Can we sync |
4ee52fc to
3b4c595
Compare
|
EWS run on previous version of this PR (hash 3b4c595) Details |
3b4c595 to
112710e
Compare
|
EWS run on previous version of this PR (hash 112710e) Details |
112710e to
031a7d1
Compare
|
EWS run on previous version of this PR (hash 031a7d1) Details |
031a7d1 to
b305577
Compare
|
EWS run on previous version of this PR (hash b305577) Details |
b305577 to
d38c0ea
Compare
|
EWS run on previous version of this PR (hash d38c0ea) Details |
d38c0ea to
2cc98ff
Compare
|
EWS run on previous version of this PR (hash 2cc98ff) Details |
https://bugs.webkit.org/show_bug.cgi?id=324175 Reviewed by NOBODY (OOPS!). Parse processing instructions in HTML and expose their pseudo-attribute accessors behind the HTMLProcessingInstructionEnabled setting, which is enabled by default and acts as a kill switch for parser fallout. Add HTMLTemplateElement.htmlFor behind the separate HTMLTemplateForEnabled setting and use <?marker>, <?start>, and <?end> processing instructions as parser insertion points for <template for>. Redirect parser output into the selected insertion point, remove replaced ranges and marker nodes, and preserve parser behavior across fragments, shadow roots, nested patches, scripts, and DOM mutations. Tests: fast/parser/html-processing-instruction-enabled.html imported/w3c/web-platform-tests/dom/nodes/MutationObserver-characterData.html imported/w3c/web-platform-tests/dom/nodes/processing-instruction-attributes.html imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/reflect-html-for.html imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/ * LayoutTests/fast/parser/html-processing-instruction-enabled-expected.txt: Added. * LayoutTests/fast/parser/html-processing-instruction-enabled.html: Added. * LayoutTests/fast/xpath/xpath-functional-test-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/dom/nodes/MutationObserver-characterData.html: * LayoutTests/imported/w3c/web-platform-tests/dom/nodes/processing-instruction-attributes-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/reflect-html-for-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-append-element-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-append-text-and-element-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-append-to-head-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-case-sensitive-dom-inserted-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-case-sensitive-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-empty-hash-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-foster-parenting-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-gradual-append-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-html-setters-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-innerHTML-ambiguous-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-innerHTML-within-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-invokes-pagehide-with-end-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-invokes-pagehide-without-end-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-move-cross-document-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-move-end-while-appending-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-move-marker-while-appending-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-move-start-while-appending-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-move-while-appending-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-multiple-cases-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-multiple-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-mutation-records-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-nested-patch-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-prepend-element-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-prepend-text-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-replace-children-with-element-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-replace-children-with-text-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-replace-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-sanitization-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-script-children-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-script-eval-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-script-replace-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-shadow-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-shadow-nested-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-shadow-root-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-style-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-style-in-head-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-supersedes-invalid-shadowrootmode-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-title-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/semantics/scripting-1/the-template-element/template-for/template-for-unclosed-content-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_url_file=html5test-com-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_url_file=processing-instructions-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_url_file=tests1-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_write_file=html5test-com-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_write_file=processing-instructions-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_write_file=tests1-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_write_single_file=html5test-com-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_write_single_file=processing-instructions-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/syntax/parsing/html5lib_write_single_file=tests1-expected.txt: * Source/WTF/Scripts/Preferences/UnifiedWebPreferences.yaml: * Source/WebCore/dom/ProcessingInstruction.cpp: (WebCore::ProcessingInstruction::updateAttributesIfNeeded): (WebCore::ProcessingInstruction::pseudoAttributeValue): (WebCore::ProcessingInstruction::hasAttributes): (WebCore::ProcessingInstruction::getAttributeNames): (WebCore::ProcessingInstruction::getAttribute): (WebCore::ProcessingInstruction::setAttribute): (WebCore::ProcessingInstruction::removeAttribute): (WebCore::ProcessingInstruction::toggleAttribute): (WebCore::ProcessingInstruction::hasAttribute): (WebCore::ProcessingInstruction::updateDataFromAttributes): (WebCore::ProcessingInstruction::checkStyleSheet): * Source/WebCore/dom/ProcessingInstruction.h: * Source/WebCore/dom/ProcessingInstruction.idl: * Source/WebCore/html/HTMLTemplateElement.cpp: (WebCore::HTMLTemplateElement::insertionTarget const): (WebCore::HTMLTemplateElement::insertionNextChild const): (WebCore::HTMLTemplateElement::prepareContentPatching): (WebCore::HTMLTemplateElement::finishParsingChildren): * Source/WebCore/html/HTMLTemplateElement.h: * Source/WebCore/html/HTMLTemplateElement.idl: * Source/WebCore/html/parser/AtomHTMLToken.h: (WebCore::AtomHTMLToken::processingInstructionTarget const): (WebCore::AtomHTMLToken::processingInstructionData const): (WebCore::AtomHTMLToken::AtomHTMLToken): * Source/WebCore/html/parser/HTMLConstructionSite.cpp: (WebCore::insert): (WebCore::HTMLConstructionSite::insertProcessingInstruction): (WebCore::HTMLConstructionSite::insertProcessingInstructionOnDocument): (WebCore::HTMLConstructionSite::insertProcessingInstructionOnHTMLHtmlElement): (WebCore::HTMLConstructionSite::insertHTMLTemplateElement): (WebCore::HTMLConstructionSite::insertTextNode): (WebCore::HTMLConstructionSite::treeScopeForCurrentNode): (WebCore::HTMLConstructionSite::containerForCurrentNode): (WebCore::HTMLConstructionSite::ownerDocumentForCurrentNode): (WebCore::registryForCurrentNode): * Source/WebCore/html/parser/HTMLConstructionSite.h: * Source/WebCore/html/parser/HTMLParserOptions.cpp: (WebCore::HTMLParserOptions::HTMLParserOptions): * Source/WebCore/html/parser/HTMLParserOptions.h: * Source/WebCore/html/parser/HTMLToken.h: (WebCore::HTMLToken::clear): (WebCore::HTMLToken::processingInstructionTarget const): (WebCore::HTMLToken::processingInstructionData const): (WebCore::HTMLToken::beginProcessingInstruction): (WebCore::HTMLToken::appendToProcessingInstructionTarget): (WebCore::HTMLToken::appendToProcessingInstructionData): * Source/WebCore/html/parser/HTMLTokenizer.cpp: (WebCore::HTMLTokenizer::emitProcessingInstruction): (WebCore::HTMLTokenizer::processToken): * Source/WebCore/html/parser/HTMLTokenizer.h: * Source/WebCore/html/parser/HTMLTreeBuilder.cpp: (WebCore::HTMLTreeBuilder::processToken): (WebCore::HTMLTreeBuilder::processProcessingInstruction): (WebCore::HTMLTreeBuilder::processTokenInForeignContent): * Source/WebCore/html/parser/HTMLTreeBuilder.h: Co-authored-by: Noam Rosenthal <nrosenthal@chromium.org>
2cc98ff to
6262d4c
Compare
|
EWS run on current version of this PR (hash 6262d4c) Details |
|
Added HTMLProcessingInstructionEnabled setting (default on) as a kill switch for the parser change. |
|
As mentioned on Slack I'd prefer we split this up into smaller patches so we can get it right. I've also filed some issues against DOM and HTML based on looking at this again. Below you'll find an AI review. I can't vouch for everything, but a lot of it seems correct. AI reviewThere are three likely bugs, some DOM API conformance issues, and the patch still bundles default-on processing instruction (PI) parsing with Likely bugs1. Removing the markers disconnects every iframe in the target. <div id=t><?start name="e">Loading…<?end></div>
<template for=e><iframe id=f srcdoc=hi></iframe></template>
<script>test(() => assert_not_equals(f.contentWindow, null))</script>Removing the markers with 2. Script runs inside
Untested repro for the re-entrant case: <div id=t><?start name="p"><iframe></iframe><?end></div>
<script>
document.querySelector("iframe").contentWindow.onpagehide = () => document.write("<p>");
document.write("<template for=p>x</template>");
</script>Wrap the removal in that incrementer, or better, run it from 3. Patched content leaves sibling and positional styles stale. <style>li:last-child { color: green }</style>
<ul><li id=a>A</li><?marker name="m"></ul>
<script>getComputedStyle(a).color;</script>
<template for=m><li>B</li></template>
<script>test(() => assert_not_equals(getComputedStyle(a).color, "rgb(0, 128, 0)"))</script>The target needs sibling and positional invalidation when the patch finishes, for the forward-direction rules too, not just what
|
| data | spec | patch |
|---|---|---|
a="x<TAB>y" |
x<TAB>y |
x y (newlines too) |
xmlns="urn:x" a="1" |
xmlns, a | nothing |
a="1" xmlns:p="urn:x" |
a, xmlns:p | a |
a="1"/><attrs b="2" |
error | a |
It also makes libxml2 reachable with arbitrary strings from any page, through getAttribute() and through marker scanning. A small parser for the PseudoAtts grammar would fix both.
6. The new ProcessingInstruction(target, data) constructor is missing. idlharness doesn't catch this because the imported interfaces/dom.idl is stale.
7. ProcessingInstruction::hasAttributes() hides Node::hasAttributes() const. The base version returns false for PIs. Rename it and use [ImplementedAs].
Parser
- Tree construction looks right. The html5lib processing instruction tests pass 123/123.
- Tokenizer: the target is stored twice, in
m_temporaryBufferand in a new 256-characterHTMLTokenbuffer that's cleared on every token. One small Latin-1 buffer would do. Also drop thestatic_cast<char>(HTMLTokenizer.cpp:1032) and theStringallocated just to compare against "xml" (:1036). - Rebase needed: it conflicts in
HTMLToken::clear()with 321805@main, which switched toshrink(0). - Small things:
HTMLParserOptions::templateForEnabledis set but never read; the code checksdocument().settings()instead (HTMLConstructionSite.cpp:644).- The
hasValidShadowRootModeloop parsesshadowrootmodeagain, though the declarative shadow DOM block below already does (:600). - If script appends a marker PI directly to a
<template>element, insertion hitsASSERT(!hasTagName(templateTag))(ContainerNode.cpp:795,:1129). That's a debug-only assert, but web-reachable.
Tests
MutationObserver-characterData.htmlwas edited in place. The next import will revert it, and upstream still expects"?processing data?". Keep the test unmodified with a FAIL baseline and fix it upstream to expect"data". The subtest is named "ProcessingInstruction", so a PI was always intended.- Three FAIL baselines are upstream test bugs, so the patch's behavior is right:
- "Unclosed element… with only start" expects
<span>New content</span>, but the template only contains "New". template-for-move-cross-document.htmlexpects "A" right before the span, but the<script>element sits between them.template-for-only-html-001.htmlloadsresources/template-for.xhtml, which doesn't exist upstream.
- "Unclosed element… with only start" expects
- The Sanitizer and stream/append API failures are expected, because WebKit doesn't implement those APIs.
- WPTs worth adding:
- an iframe in the patch (Fix typo in domain.endsWith() check for hulu.com #1);
- sibling and positional style after patching (Build support for Haiku operating system #3);
- attributes surviving insertion and clone ([git-webkit] Add pull-request command (Part) #4);
- U+0000 in PI data;
- end of input without
</template>; document.write()from pagehide during patching (Build support for Haiku operating system #2).
Landing
- Performance follow-ups:
- finding markers walks the whole
<html>subtree for every<template for>; - the preload scanner treats
<template for>contents as inert, so nothing in a patch is preloaded.
- finding markers walks the whole
🧪 ios-wk2-wpt
6262d4c
6262d4c
🛠 playstation