mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-06-11 09:35:59 -04:00
Merge pull request #2500 from lightpanda-io/parseHtmlAsChildren_assertion
parseHtmlAsChildren handling for unexpected dom (custom element callb…
This commit is contained in:
@@ -3644,10 +3644,16 @@ pub fn parseHtmlAsChildren(self: *Frame, node: *Node, html: []const u8) !void {
|
||||
var parser = Parser.init(self.call_arena, node, self);
|
||||
parser.parseFragment(html);
|
||||
|
||||
// https://github.com/servo/html5ever/issues/583
|
||||
// html5ever wraps fragment output in an <html> element; unwrap so its
|
||||
// children land directly on `node`. See https://github.com/servo/html5ever/issues/583.
|
||||
// Because of custom element callbacks, the structure might not be what
|
||||
// we expect, and nodes might be altogether removed. We deal with this in a
|
||||
// few different places, but always the same way: leave it as-is.
|
||||
const children = node._children orelse return;
|
||||
const first = children.one;
|
||||
lp.assert(first.is(Element.Html.Html) != null, "Frame.parseHtmlAsChildren root", .{ .type = first._type });
|
||||
const first = children.first();
|
||||
if (first.is(Element.Html.Html) == null) {
|
||||
return;
|
||||
}
|
||||
node._children = first._children;
|
||||
|
||||
if (self.hasMutationObservers()) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<body>
|
||||
<script src="../testing.js"></script>
|
||||
|
||||
<!-- Frame.parseHtmlAsChildren extracts children from the temporary
|
||||
<html> element the fragment parser leaves at the top of the parse
|
||||
result. A custom element's connectedCallback fires synchronously
|
||||
during that parse, so it can reach two levels up (this.parentNode is
|
||||
the temporary <html>; this.parentNode.parentNode is the original
|
||||
element receiving innerHTML) and replace the temporary wrapper with
|
||||
a text node before the post-parse step inspects the result. -->
|
||||
<script id="connected_callback_replaces_wrapper">
|
||||
{
|
||||
class WrapperReplacer extends HTMLElement {
|
||||
connectedCallback() {
|
||||
const wrapper = this.parentNode;
|
||||
if (!wrapper) return;
|
||||
const host = wrapper.parentNode;
|
||||
if (!host) return;
|
||||
host.removeChild(wrapper);
|
||||
host.appendChild(document.createTextNode(''));
|
||||
}
|
||||
}
|
||||
customElements.define('wrapper-replacer-1', WrapperReplacer);
|
||||
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
host.innerHTML = '<wrapper-replacer-1></wrapper-replacer-1>';
|
||||
|
||||
// The point of this test is to reach this line without aborting.
|
||||
testing.expectTrue(host.firstChild !== null);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user