@@ -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