Handle unmatched closing tags and SVG parsing - #687
olavoasantos wants to merge 1 commit into
Conversation
ee2462e to
4805586
Compare
4805586 to
2891a92
Compare
JoviDeCroock
left a comment
There was a problem hiding this comment.
I think the following is still problematic
<section>
<template>
Before
</section>
After
</template>
not sure what the expected result should be though, we search backwards through every open frame which means we forget that we should be closing template
2891a92 to
9f62283
Compare
9f62283 to
81f87c8
Compare
|
Thanks for the template-boundary fix and regression test in the restack. That addresses the earlier scope concern. Two corrections remain in the SVG parsing branch at 1. Preserve SVG-to-HTML re-entryThe namespace selection only recognizes a lowercased, unprefixed const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
const title = document.createElementNS(SVG_NAMESPACE, 'title');
title.innerHTML = '<x-label>Help</x-label>';Native/base create an HTML child; the reviewed implementation creates an SVG child. With a registered HTML integration points depend on namespace plus exact There is also a distinct HTML breakout path: assigning 2. Don't interpret parsed HTML token names as XML QNamesThe new const svg = document.createElementNS(SVG_NAMESPACE, 'svg');
svg.innerHTML = '<xml:item></xml:item>';
// Reviewed implementation: NamespaceError
// Native: accepted; localName === 'xml:item', prefix === null
Please use the existing internal Focused coverage: integration-point namespaces and constructor counts; non-integration controls; HTML breakout namespaces/placement; literal-colon localName/prefix/namespace and no parser exception, with public QName-validation controls still rejecting invalid API arguments. These are parser-specific corrections, not a request to rewrite the whole HTML parser. Evidence boundary: the native/base/head repros and full focused suites were run at |
|
i checked this case against native parsing. The expected result is |
81f87c8 to
6c5ea0f
Compare
andrewiggins
left a comment
There was a problem hiding this comment.
Some of Henry's comment isn't yet addressed. Let us know when those are addressed and I'll come back and review.
Although, I'd consider deferring supporting HTML breakout tags in SVG initially. That seems like a slightly larger change then just "adding SVG parsing" that I'd like to weigh separately to see how much it costs.
| } else if (token[5]) { | ||
| parent = stack.pop()?.target ?? root; | ||
| const closingTag = asciiLowercase(token[5]); | ||
| for (let index = stack.length - 1; index >= 0; index--) { |
There was a problem hiding this comment.
I don't think we need to address this right now, but just FYI - this is a quadratic look up in a catastrophic case of malformed markup. I think that's fine for now but just want to note it for posterity if we come across this being a problem in the future.
There was a problem hiding this comment.
yea, agreed. let's keep the quadratic malformed-input case as a known tradeoff for now instead of expanding this PR.
6c5ea0f to
e164e79
Compare
|
The remaining SVG cases are addressed on
@andrewiggins leaving breakout out would keep the regression against base where |
|
Thanks, the SVG integration-point, breakout, and literal-colon/QName corrections now pass on One remaining P2 correction: please keep the namespace routing SVG-scoped, or explicitly preserve the already-working non-SVG HTML integration contexts. At Here is a minimal regression test using only public APIs: it('preserves HTML custom elements in an existing non-SVG context', () => {
const window = new Window();
const document = window.document;
let constructions = 0;
class Label extends window.HTMLElement {
constructor() {
super();
constructions += 1;
}
}
window.customElements.define('x-label', Label);
const context = document.createElementNS(
'http://www.w3.org/1998/Math/MathML',
'mtext',
);
context.innerHTML = '<x-label>Help</x-label>';
expect(context.children[0].namespaceURI).toBe(
'http://www.w3.org/1999/xhtml',
);
expect(context.children[0]).toBeInstanceOf(Label);
expect(constructions).toBe(1);
});Native and actual base create an HTML child and invoke the registered constructor once. This head creates a generic MathML element and invokes it zero times. The same issue reproduces for This also has observable core impact: with a registered The suggestion is to preserve existing behavior while adding SVG support, not to implement a full MathML parser. Please retain the now-passing SVG integration/non-integration controls, breakout placement, and public QName validation while adding the non-SVG regression coverage. This broad inheritance was present in the earlier implementation too; it is not a new restack-only defect. Validation: 393 existing polyfill tests, 63 focused core tests, locked polyfill typecheck, formatting, and current CI pass. Four actual-core SVG flows pass; the non-SVG flow above regresses. No production fix or full locked-repository/live Shell/admin validation performed. The separate maintainer discussion about breakout scope remains open. |
Problem
The parser popped one frame for every closing tag without checking its name. An unmatched closing tag could therefore close the current element and redirect following content into the wrong parent. It also created all parsed elements with the HTML factory, so SVG markup assigned through
innerHTMLlost SVG namespace and element semantics.Impact
Minor. The exposed limited parser could build a different tree after an unmatched closing tag, and parsed SVG could be an HTML
Elementrather than anSVGElement. That affects subsequent tree queries, namespace-sensitive operations, and serialized worker-side DOM output.Reproduction
Before this change,
</wrong>popped thespanframe, makingba child ofsection. It now ignores the unmatched closing tag and serializes as<section><span>Before<b>After</b></span></section>. Parsed<svg>descendants now retain the SVG namespace rather than being created as HTML elements.Change
<svg>and its descendants in the SVG namespace; inherit an SVGinnerHTMLcontext; and switch to HTML insideforeignObject, with nested<svg>switching back to SVG.<template>elements as SVG elements rather than HTML templates.The change deliberately improves these supported parser paths without claiming full browser-grade malformed-markup recovery or foreign-content parsing.
Tests
Extends
packages/polyfill/source/tests/inner-html-parsing.test.tswith unmatched and ancestor closing-tag cases, top-level and inherited SVG namespace assertions,foreignObjectand nested-SVG boundaries, template insertion-target preservation after an unmatched closing tag, and SVG template-descendant behavior.Stack
serialize-template-contentThe nullable-namespace type correction now belongs to #686, leaving this layer scoped to closing-tag and SVG parsing behavior.
Validation
Fresh GitHub CI on restacked head
2891a92passes: