Skip to content

Commit 0a5f060

Browse files
add tests and simplify walker traversal
1 parent f1e5134 commit 0a5f060

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

src/browser/dom/node.zig

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,17 @@ pub const Node = struct {
201201
const self_owner = try parser.nodeOwnerDocument(self);
202202
const child_owner = try parser.nodeOwnerDocument(child);
203203

204+
// If the node to be inserted has a different ownerDocument than the parent node,
205+
// modern browsers automatically adopt the node and its descendants into
206+
// the parent's ownerDocument.
207+
// This process is known as adoption.
208+
// (7.1) https://dom.spec.whatwg.org/#concept-node-insert
204209
if (child_owner == null or (child_owner.? != self_owner.?)) {
205210
const w = Walker{};
206-
child.owner = self_owner;
207211
var current = child;
208-
while (try w.get_next(child, current)) |current_node| {
209-
current_node.owner = self_owner;
210-
current = current_node;
212+
while (true) {
213+
current.owner = self_owner;
214+
current = try w.get_next(child, current) orelse break;
211215
}
212216
}
213217

@@ -306,13 +310,17 @@ pub const Node = struct {
306310
const self_owner = try parser.nodeOwnerDocument(self);
307311
const new_node_owner = try parser.nodeOwnerDocument(new_node);
308312

313+
// If the node to be inserted has a different ownerDocument than the parent node,
314+
// modern browsers automatically adopt the node and its descendants into
315+
// the parent's ownerDocument.
316+
// This process is known as adoption.
317+
// (7.1) https://dom.spec.whatwg.org/#concept-node-insert
309318
if (new_node_owner == null or (new_node_owner.? != self_owner.?)) {
310319
const w = Walker{};
311-
new_node.owner = self_owner;
312320
var current = new_node;
313-
while (try w.get_next(new_node, current)) |current_node| {
314-
current_node.owner = self_owner;
315-
current = current_node;
321+
while(true) {
322+
current.owner = self_owner;
323+
current = try w.get_next(new_node, current) orelse break;
316324
}
317325
}
318326

@@ -746,3 +754,48 @@ test "Browser.DOM.node" {
746754
.{ "Node.NOTATION_NODE", "12" },
747755
}, .{});
748756
}
757+
758+
test "Browser.DOM.node.owner" {
759+
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html=
760+
\\ <div id="target-container">
761+
\\ <p id="reference-node">
762+
\\ I am the original reference node.
763+
\\ </p>
764+
\\ </div>"
765+
});
766+
767+
defer runner.deinit();
768+
769+
try runner.testCases(&.{
770+
.{
771+
\\ const parser = new DOMParser();
772+
\\ const newDoc = parser.parseFromString('<div id="new-node"><p>Hey</p><span>Marked</span></div>', 'text/html');
773+
774+
\\ const newNode = newDoc.getElementById('new-node');
775+
776+
\\ const parent = document.getElementById('target-container');
777+
\\ const referenceNode = document.getElementById('reference-node');
778+
779+
\\ parent.insertBefore(newNode, referenceNode);
780+
\\ const k = document.getElementById('new-node');
781+
\\ const ptag = k.querySelector('p');
782+
\\ const spanTag = k.querySelector('span');
783+
\\ const anotherDoc = parser.parseFromString('<div id="another-new-node"></div>', 'text/html');
784+
\\ const anotherNewNode = anotherDoc.getElementById('another-new-node');
785+
\\
786+
\\ parent.appendChild(anotherNewNode)
787+
,
788+
"[object HTMLDivElement]",
789+
},
790+
791+
.{"parent.ownerDocument === newNode.ownerDocument", "true" },
792+
.{"parent.ownerDocument === anotherNewNode.ownerDocument", "true"},
793+
.{"newNode.firstChild.nodeName", "P"},
794+
.{"ptag.ownerDocument === parent.ownerDocument", "true"},
795+
.{"spanTag.ownerDocument === parent.ownerDocument", "true"},
796+
.{"parent.contains(newNode)", "true"},
797+
.{"parent.contains(anotherNewNode)", "true"},
798+
.{"anotherDoc.contains(anotherNewNode)", "false"},
799+
.{"newDoc.contains(newNode)", "false"},
800+
}, .{});
801+
}

0 commit comments

Comments
 (0)