Skip to content

Commit 0e04831

Browse files
Implement circa 2021 spec change for fragment parsing in foreign content
This change brings us into conformance with the “make breaking out of foreign content apply in innerHTML” requirements from the HTML spec PR at whatwg/html#6399 — and into interoperability with current WebKit and Blink behaviour, making fragment parsing break out of foreign content in the same way document parsing does. Before this code change, when parsing elements like <p>, <div>, and <nobr> inside SVG/MathML via innerHTML, they would stay in the foreign namespace. But, with this change, they now correctly “break out”, and are created in the HTML namespace. TreeBuilder.java ---------------- - Start tags: Remove fragment-only restriction on break-out behavior - End tags: Allow </p> and </br> to reach mode-handling-in-fragment case - Use currentPtr > 0 to preserve context element when popping
1 parent 6904dd1 commit 0e04831

File tree

3 files changed

+26
-14
lines changed

3 files changed

+26
-14
lines changed

src/nu/validator/htmlparser/impl/TreeBuilder.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,12 +1531,19 @@ public final void startTag(ElementName elementName,
15311531
if (!(group == FONT && !(attributes.contains(AttributeName.COLOR)
15321532
|| attributes.contains(AttributeName.FACE) || attributes.contains(AttributeName.SIZE)))) {
15331533
errHtmlStartTagInForeignContext(name);
1534-
if (!fragment) {
1535-
while (!isSpecialParentInForeign(stack[currentPtr])) {
1536-
popForeign(-1, -1);
1537-
}
1534+
// Pop until we reach an HTML namespace element,
1535+
// HTML integration point, or MathML text integration point.
1536+
// In fragment case, stop before popping the context element.
1537+
while (currentPtr > 0 && !isSpecialParentInForeign(stack[currentPtr])) {
1538+
popForeign(-1, -1);
1539+
}
1540+
if (currentPtr > 0 || isSpecialParentInForeign(stack[currentPtr])) {
1541+
// Popped to an HTML element or integration point
15381542
continue starttagloop;
1539-
} // else fall thru
1543+
}
1544+
// In fragment case with foreign context, fall through
1545+
// to let switch(mode) handle the token in HTML namespace
1546+
break;
15401547
}
15411548
// CPPONLY: MOZ_FALLTHROUGH;
15421549
default:
@@ -3220,6 +3227,11 @@ public final void endTag(ElementName elementName) throws SAXException {
32203227
for (;;) {
32213228
if (eltPos == 0) {
32223229
assert fragment: "We can get this close to the root of the stack in foreign content only in the fragment case.";
3230+
// For </p> and </br>, continue to mode handling
3231+
// which will create implied start tags
3232+
if (group == P || group == BR) {
3233+
break; // break from inner loop, continue to switch(mode)
3234+
}
32233235
break endtagloop;
32243236
}
32253237
if (stack[eltPos].name == name) {
@@ -3564,12 +3576,10 @@ public final void endTag(ElementName elementName) throws SAXException {
35643576
eltPos = findLastInButtonScope("p");
35653577
if (eltPos == TreeBuilder.NOT_FOUND_ON_STACK) {
35663578
errNoElementToCloseButEndTagSeen("p");
3567-
// XXX Can the 'in foreign' case happen anymore?
35683579
if (isInForeign()) {
35693580
errHtmlStartTagInForeignContext(name);
3570-
// Check for currentPtr for the fragment
3571-
// case.
3572-
while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
3581+
// Pop foreign elements, but keep context element in fragment case
3582+
while (currentPtr > 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
35733583
pop();
35743584
}
35753585
}
@@ -3650,11 +3660,9 @@ public final void endTag(ElementName elementName) throws SAXException {
36503660
case BR:
36513661
errEndTagBr();
36523662
if (isInForeign()) {
3653-
// XXX can this happen anymore?
36543663
errHtmlStartTagInForeignContext(name);
3655-
// Check for currentPtr for the fragment
3656-
// case.
3657-
while (currentPtr >= 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
3664+
// Pop foreign elements, but keep context element in fragment case
3665+
while (currentPtr > 0 && stack[currentPtr].ns != "http://www.w3.org/1999/xhtml") {
36583666
pop();
36593667
}
36603668
}

test-src/nu/validator/htmlparser/test/Html5libTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ private static class TestVisitor extends SimpleFileVisitor<Path> {
102102

103103
private final TestConsumer runner;
104104

105+
// Files to skip due to known failures
106+
private static final java.util.Set<String> SKIP_FILES = java.util.Set.of(
107+
);
108+
105109
private TestVisitor(boolean skipScripted, String requiredTestExtension,
106110
TestConsumer runner) {
107111
this.skipScripted = skipScripted;
Submodule html5lib-tests updated 60 files

0 commit comments

Comments
 (0)