From 288379aa7dd8da49eed42dec9eb5ba75f8ad194b Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Thu, 16 Oct 2025 19:08:33 +0800 Subject: [PATCH] support the composed option of getRootNode() --- src/browser/dom/node.zig | 28 ++++++++++++++++++++-------- src/tests/dom/node.html | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/browser/dom/node.zig b/src/browser/dom/node.zig index 71b88e0e..b84ae9d3 100644 --- a/src/browser/dom/node.zig +++ b/src/browser/dom/node.zig @@ -360,18 +360,30 @@ pub const Node = struct { node: Union, }; pub fn _getRootNode(self: *parser.Node, options: ?struct { composed: bool = false }, page: *Page) !GetRootNodeResult { - if (options) |options_| if (options_.composed) { - log.warn(.web_api, "not implemented", .{ .feature = "getRootNode composed" }); - }; + const composed = if (options) |opts| opts.composed else false; - const root = parser.nodeGetRootNode(self); - if (page.getNodeState(root)) |state| { - if (state.shadow_root) |sr| { - return .{ .shadow_root = sr }; + var current_root = parser.nodeGetRootNode(self); + + while (true) { + const node_type = parser.nodeType(current_root); + + if (node_type == .document_fragment) { + if (parser.documentFragmentGetHost(@ptrCast(current_root))) |host| { + if (page.getNodeState(host)) |state| { + if (state.shadow_root) |sr| { + if (!composed) { + return .{ .shadow_root = sr }; + } + current_root = parser.nodeGetRootNode(@ptrCast(sr.host)); + continue; + } + } + } } + break; } - return .{ .node = try Node.toInterface(root) }; + return .{ .node = try Node.toInterface(current_root) }; } pub fn _hasChildNodes(self: *parser.Node) bool { diff --git a/src/tests/dom/node.html b/src/tests/dom/node.html index cdea68d6..ae9b8a3e 100644 --- a/src/tests/dom/node.html +++ b/src/tests/dom/node.html @@ -7,6 +7,7 @@

And

+
@@ -36,6 +37,26 @@ let first_child = content.firstChild.nextSibling; // nextSibling because of line testing.expectEqual('HTMLDocument', content.getRootNode().__proto__.constructor.name); + +