@@ -202,16 +202,26 @@ pub const Node = struct {
202202 const new_node_owner = try parser .nodeOwnerDocument (child );
203203
204204 if (new_node_owner == null or (new_node_owner .? != self_owner .? )) {
205+ var arena = std .heap .ArenaAllocator .init (std .heap .page_allocator );
206+ defer arena .deinit ();
207+
208+ const allocator = arena .allocator ();
209+ var worklist = std .ArrayList (* parser .Node ).init (allocator );
210+
205211 child .owner = self_owner ;
206- // recursively set the owner for all children
207- var next : ? * parser.Node = child ;
208- while (next ) | n | {
209- next = try parser .nodeFirstChild (n ) orelse break ;
210- if (next ) | child_next | {
211- child_next .owner = self_owner ;
212+ try worklist .append (child );
213+
214+ // change ownerDocument of all children of a given node
215+ while (worklist .pop ()) | current_node | {
216+ var maybe_child : ? * parser.Node = try parser .nodeFirstChild (current_node );
217+ while (maybe_child ) | child_node | {
218+ child_node .owner = self_owner ;
219+ try worklist .append (child_node );
220+ maybe_child = try parser .nodeNextSibling (child_node );
212221 }
213222 }
214223 }
224+
215225 // TODO: DocumentFragment special case
216226 const res = try parser .nodeAppendChild (self , child );
217227 return try Node .toInterface (res );
@@ -306,15 +316,26 @@ pub const Node = struct {
306316 pub fn _insertBefore (self : * parser.Node , new_node : * parser.Node , ref_node_ : ? * parser.Node ) ! Union {
307317 const self_owner = try parser .nodeOwnerDocument (self );
308318 const new_node_owner = try parser .nodeOwnerDocument (new_node );
319+
309320 if (new_node_owner == null or (new_node_owner .? != self_owner .? )) {
321+
322+ var arena = std .heap .ArenaAllocator .init (std .heap .page_allocator );
323+ defer arena .deinit ();
324+ const allocator = arena .allocator ();
325+
326+ var worklist = std .ArrayList (* parser .Node ).init (allocator );
310327 new_node .owner = self_owner ;
311- var next : ? * parser.Node = new_node ;
312- while (next ) | n | {
313- next = try parser .nodeFirstChild (n ) orelse break ;
314- if (next ) | child_next | {
315- child_next .owner = self_owner ;
328+ try worklist .append (new_node );
329+
330+ while (worklist .pop ()) | current_node | {
331+ var maybe_child : ? * parser.Node = try parser .nodeFirstChild (current_node );
332+ while (maybe_child ) | child | {
333+ child .owner = self_owner ;
334+ try worklist .append (child );
335+ maybe_child = try parser .nodeNextSibling (child );
316336 }
317337 }
338+
318339 }
319340 if (ref_node_ ) | ref_node | {
320341 return Node .toInterface (try parser .nodeInsertBefore (self , new_node , ref_node ));
0 commit comments