fix: traverse all children correctly

This commit is contained in:
Srikanth
2025-08-04 13:00:03 +05:30
parent b4014e8c24
commit c533b10e19

View File

@@ -202,16 +202,26 @@ pub const Node = struct {
const new_node_owner = try parser.nodeOwnerDocument(child); const new_node_owner = try parser.nodeOwnerDocument(child);
if (new_node_owner == null or (new_node_owner.? != self_owner.?)) { if (new_node_owner == null or (new_node_owner.? != self_owner.?)) {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var worklist = std.ArrayList(*parser.Node).init(allocator);
child.owner = self_owner; child.owner = self_owner;
// recursively set the owner for all children try worklist.append(child);
var next: ?*parser.Node = child;
while (next) |n| { // change ownerDocument of all children of a given node
next = try parser.nodeFirstChild(n) orelse break; while (worklist.pop()) |current_node| {
if (next) |child_next| { var maybe_child: ?*parser.Node = try parser.nodeFirstChild(current_node);
child_next.owner = self_owner; while (maybe_child) |child_node| {
child_node.owner = self_owner;
try worklist.append(child_node);
maybe_child = try parser.nodeNextSibling(child_node);
} }
} }
} }
// TODO: DocumentFragment special case // TODO: DocumentFragment special case
const res = try parser.nodeAppendChild(self, child); const res = try parser.nodeAppendChild(self, child);
return try Node.toInterface(res); return try Node.toInterface(res);
@@ -306,15 +316,26 @@ pub const Node = struct {
pub fn _insertBefore(self: *parser.Node, new_node: *parser.Node, ref_node_: ?*parser.Node) !Union { pub fn _insertBefore(self: *parser.Node, new_node: *parser.Node, ref_node_: ?*parser.Node) !Union {
const self_owner = try parser.nodeOwnerDocument(self); const self_owner = try parser.nodeOwnerDocument(self);
const new_node_owner = try parser.nodeOwnerDocument(new_node); const new_node_owner = try parser.nodeOwnerDocument(new_node);
if (new_node_owner == null or (new_node_owner.? != self_owner.?)) { if (new_node_owner == null or (new_node_owner.? != self_owner.?)) {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var worklist = std.ArrayList(*parser.Node).init(allocator);
new_node.owner = self_owner; new_node.owner = self_owner;
var next: ?*parser.Node = new_node; try worklist.append(new_node);
while (next) |n| {
next = try parser.nodeFirstChild(n) orelse break; while (worklist.pop()) |current_node| {
if (next) |child_next| { var maybe_child: ?*parser.Node = try parser.nodeFirstChild(current_node);
child_next.owner = self_owner; while (maybe_child) |child| {
child.owner = self_owner;
try worklist.append(child);
maybe_child = try parser.nodeNextSibling(child);
} }
} }
} }
if (ref_node_) |ref_node| { if (ref_node_) |ref_node| {
return Node.toInterface(try parser.nodeInsertBefore(self, new_node, ref_node)); return Node.toInterface(try parser.nodeInsertBefore(self, new_node, ref_node));