Skip to content

Commit c533b10

Browse files
fix: traverse all children correctly
1 parent b4014e8 commit c533b10

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

src/browser/dom/node.zig

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)