Skip to content

Commit 288379a

Browse files
committed
support the composed option of getRootNode()
1 parent cc0c1bc commit 288379a

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

src/browser/dom/node.zig

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -360,18 +360,30 @@ pub const Node = struct {
360360
node: Union,
361361
};
362362
pub fn _getRootNode(self: *parser.Node, options: ?struct { composed: bool = false }, page: *Page) !GetRootNodeResult {
363-
if (options) |options_| if (options_.composed) {
364-
log.warn(.web_api, "not implemented", .{ .feature = "getRootNode composed" });
365-
};
363+
const composed = if (options) |opts| opts.composed else false;
364+
365+
var current_root = parser.nodeGetRootNode(self);
366366

367-
const root = parser.nodeGetRootNode(self);
368-
if (page.getNodeState(root)) |state| {
369-
if (state.shadow_root) |sr| {
370-
return .{ .shadow_root = sr };
367+
while (true) {
368+
const node_type = parser.nodeType(current_root);
369+
370+
if (node_type == .document_fragment) {
371+
if (parser.documentFragmentGetHost(@ptrCast(current_root))) |host| {
372+
if (page.getNodeState(host)) |state| {
373+
if (state.shadow_root) |sr| {
374+
if (!composed) {
375+
return .{ .shadow_root = sr };
376+
}
377+
current_root = parser.nodeGetRootNode(@ptrCast(sr.host));
378+
continue;
379+
}
380+
}
381+
}
371382
}
383+
break;
372384
}
373385

374-
return .{ .node = try Node.toInterface(root) };
386+
return .{ .node = try Node.toInterface(current_root) };
375387
}
376388

377389
pub fn _hasChildNodes(self: *parser.Node) bool {

src/tests/dom/node.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<p id="para"> And</p>
88
<!--comment-->
99
</div>
10+
<div id="rootNodeComposed"></div>
1011
</body>
1112

1213
<script src="../testing.js"></script>
@@ -36,6 +37,26 @@
3637
testing.expectEqual('HTMLDocument', content.getRootNode().__proto__.constructor.name);
3738
</script>
3839

40+
<script id=getRootNodeComposed>
41+
const testContainer = $('#rootNodeComposed');
42+
const shadowHost = document.createElement('div');
43+
testContainer.appendChild(shadowHost);
44+
const shadowRoot = shadowHost.attachShadow({ mode: 'open' });
45+
const shadowChild = document.createElement('span');
46+
shadowRoot.appendChild(shadowChild);
47+
48+
testing.expectEqual('ShadowRoot', shadowChild.getRootNode().__proto__.constructor.name);
49+
testing.expectEqual('ShadowRoot', shadowChild.getRootNode({ composed: false }).__proto__.constructor.name);
50+
testing.expectEqual('HTMLDocument', shadowChild.getRootNode({ composed: true }).__proto__.constructor.name);
51+
testing.expectEqual('HTMLDocument', shadowHost.getRootNode().__proto__.constructor.name);
52+
53+
const disconnected = document.createElement('div');
54+
const disconnectedChild = document.createElement('span');
55+
disconnected.appendChild(disconnectedChild);
56+
testing.expectEqual('HTMLDivElement', disconnectedChild.getRootNode().__proto__.constructor.name);
57+
testing.expectEqual('HTMLDivElement', disconnectedChild.getRootNode({ composed: true }).__proto__.constructor.name);
58+
</script>
59+
3960
<script id=firstChild>
4061
let body_first_child = document.body.firstChild;
4162
testing.expectEqual('div', body_first_child.localName);

0 commit comments

Comments
 (0)