From 0a5f060d1b7b21054b89c1a47e107ce291627953 Mon Sep 17 00:00:00 2001 From: Srikanth Date: Mon, 4 Aug 2025 23:53:29 +0530 Subject: [PATCH] add tests and simplify walker traversal --- src/browser/dom/node.zig | 69 +++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/src/browser/dom/node.zig b/src/browser/dom/node.zig index af462de2..3dd6a06f 100644 --- a/src/browser/dom/node.zig +++ b/src/browser/dom/node.zig @@ -201,13 +201,17 @@ pub const Node = struct { const self_owner = try parser.nodeOwnerDocument(self); const child_owner = try parser.nodeOwnerDocument(child); + // If the node to be inserted has a different ownerDocument than the parent node, + // modern browsers automatically adopt the node and its descendants into + // the parent's ownerDocument. + // This process is known as adoption. + // (7.1) https://dom.spec.whatwg.org/#concept-node-insert if (child_owner == null or (child_owner.? != self_owner.?)) { const w = Walker{}; - child.owner = self_owner; var current = child; - while (try w.get_next(child, current)) |current_node| { - current_node.owner = self_owner; - current = current_node; + while (true) { + current.owner = self_owner; + current = try w.get_next(child, current) orelse break; } } @@ -306,13 +310,17 @@ pub const Node = struct { const self_owner = try parser.nodeOwnerDocument(self); const new_node_owner = try parser.nodeOwnerDocument(new_node); + // If the node to be inserted has a different ownerDocument than the parent node, + // modern browsers automatically adopt the node and its descendants into + // the parent's ownerDocument. + // This process is known as adoption. + // (7.1) https://dom.spec.whatwg.org/#concept-node-insert if (new_node_owner == null or (new_node_owner.? != self_owner.?)) { const w = Walker{}; - new_node.owner = self_owner; var current = new_node; - while (try w.get_next(new_node, current)) |current_node| { - current_node.owner = self_owner; - current = current_node; + while(true) { + current.owner = self_owner; + current = try w.get_next(new_node, current) orelse break; } } @@ -746,3 +754,48 @@ test "Browser.DOM.node" { .{ "Node.NOTATION_NODE", "12" }, }, .{}); } + +test "Browser.DOM.node.owner" { + var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html= + \\
+ \\

+ \\ I am the original reference node. + \\

+ \\
" + }); + + defer runner.deinit(); + + try runner.testCases(&.{ + .{ + \\ const parser = new DOMParser(); + \\ const newDoc = parser.parseFromString('

Hey

Marked
', 'text/html'); + + \\ const newNode = newDoc.getElementById('new-node'); + + \\ const parent = document.getElementById('target-container'); + \\ const referenceNode = document.getElementById('reference-node'); + + \\ parent.insertBefore(newNode, referenceNode); + \\ const k = document.getElementById('new-node'); + \\ const ptag = k.querySelector('p'); + \\ const spanTag = k.querySelector('span'); + \\ const anotherDoc = parser.parseFromString('
', 'text/html'); + \\ const anotherNewNode = anotherDoc.getElementById('another-new-node'); + \\ + \\ parent.appendChild(anotherNewNode) + , + "[object HTMLDivElement]", + }, + + .{"parent.ownerDocument === newNode.ownerDocument", "true" }, + .{"parent.ownerDocument === anotherNewNode.ownerDocument", "true"}, + .{"newNode.firstChild.nodeName", "P"}, + .{"ptag.ownerDocument === parent.ownerDocument", "true"}, + .{"spanTag.ownerDocument === parent.ownerDocument", "true"}, + .{"parent.contains(newNode)", "true"}, + .{"parent.contains(anotherNewNode)", "true"}, + .{"anotherDoc.contains(anotherNewNode)", "false"}, + .{"newDoc.contains(newNode)", "false"}, + }, .{}); +} \ No newline at end of file