diff --git a/src/browser/dom/element.zig b/src/browser/dom/element.zig index ad435038..f8cde653 100644 --- a/src/browser/dom/element.zig +++ b/src/browser/dom/element.zig @@ -127,16 +127,40 @@ pub const Element = struct { // remove existing children try Node.removeChildren(node); - // get fragment body children - const children = try parser.documentFragmentBodyChildren(fragment) orelse return; + // I'm not sure what the exact behavior is supposed to be. Initially, + // we were only copying the body of the document fragment. But it seems + // like head elements should be copied too. Specifically, some sites + // create script tags via innerHTML, which we need to capture. + // If you play with this in a browser, you should notice that the + // behavior is different depending on whether you're in a blank page + // or an actual document. In a blank page, something like: + // x.innerHTML = ''; + // does _not_ create an empty script, but in a real page, it does. Weird. + const fragment_node = parser.documentFragmentToNode(fragment); + const html = try parser.nodeFirstChild(fragment_node) orelse return; + const head = try parser.nodeFirstChild(html) orelse return; + { + // First, copy some of the head element + const children = try parser.nodeGetChildNodes(head); + const ln = try parser.nodeListLength(children); + for (0..ln) |_| { + // always index 0, because nodeAppendChild moves the node out of + // the nodeList and into the new tree + const child = try parser.nodeListItem(children, 0) orelse continue; + _ = try parser.nodeAppendChild(node, child); + } + } - // append children to the node - const ln = try parser.nodeListLength(children); - for (0..ln) |_| { - // always index 0, because ndoeAppendChild moves the node out of - // the nodeList and into the new tree - const child = try parser.nodeListItem(children, 0) orelse continue; - _ = try parser.nodeAppendChild(node, child); + { + const body = try parser.nodeNextSibling(head) orelse return; + const children = try parser.nodeGetChildNodes(body); + const ln = try parser.nodeListLength(children); + for (0..ln) |_| { + // always index 0, because nodeAppendChild moves the node out of + // the nodeList and into the new tree + const child = try parser.nodeListItem(children, 0) orelse continue; + _ = try parser.nodeAppendChild(node, child); + } } } @@ -688,5 +712,10 @@ test "Browser.DOM.Element" { try runner.testCases(&.{ .{ "document.createElement('a').hasAttributes()", "false" }, + .{ "var fc; (fc = document.createElement('div')).innerHTML = '" }, + + .{ "fc; (fc = document.createElement('div')).innerHTML = '
hello
" }, }, .{}); } diff --git a/src/browser/netsurf.zig b/src/browser/netsurf.zig index 0a34bcb9..0b11a1dd 100644 --- a/src/browser/netsurf.zig +++ b/src/browser/netsurf.zig @@ -1925,18 +1925,6 @@ pub inline fn documentFragmentToNode(doc: *DocumentFragment) *Node { return @as(*Node, @alignCast(@ptrCast(doc))); } -pub fn documentFragmentBodyChildren(doc: *DocumentFragment) !?*NodeList { - const node = documentFragmentToNode(doc); - const html = try nodeFirstChild(node) orelse return null; - // TODO unref - const head = try nodeFirstChild(html) orelse return null; - // TODO unref - const body = try nodeNextSibling(head) orelse return null; - // TODO unref - - return try nodeGetChildNodes(body); -} - // Document Position pub const DocumentPosition = enum(u32) {