Skip to content

Commit 8b9084c

Browse files
committed
cdp: dispatch the correct dom hierarchy wit setChildNodes
1 parent 1146453 commit 8b9084c

File tree

1 file changed

+73
-16
lines changed

1 file changed

+73
-16
lines changed

src/cdp/domains/dom.zig

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,29 +78,86 @@ fn performSearch(cmd: anytype) !void {
7878

7979
// dispatch setChildNodesEvents to inform the client of the subpart of node
8080
// tree covering the results.
81-
for (list.nodes.items) |n| {
82-
// retrieve the node's parent
83-
if (try parser.nodeParentNode(n)) |p| {
84-
// Register the parent and send the node.
85-
const parent_node = try bc.node_registry.register(p);
86-
const node = bc.node_registry.lookup_by_node.get(n) orelse unreachable;
87-
// Should-we return one DOM.setChildNodes event per parentId
88-
// containing all its children in the nodes array?
89-
try cmd.sendEvent("DOM.setChildNodes", .{
90-
.parentId = parent_node.id,
91-
.nodes = .{bc.nodeWriter(node, .{})},
92-
}, .{
93-
.session_id = bc.session_id.?,
94-
});
95-
}
96-
}
81+
try dispatchSetChildNodes(cmd, list.nodes.items);
9782

9883
return cmd.sendResult(.{
9984
.searchId = search.name,
10085
.resultCount = @as(u32, @intCast(search.node_ids.len)),
10186
}, .{});
10287
}
10388

89+
// dispatchSetChildNodes send the setChildNodes event for the whole DOM tree
90+
// hierarchy of each nodes.
91+
// If a parent has already been registred, we don't re-send a setChildNodes
92+
// event anymore.
93+
// We dispatch event in the reverse order: from the top level to the direct parents.
94+
fn dispatchSetChildNodes(cmd: anytype, nodes: []*parser.Node) !void {
95+
const arena = cmd.arena;
96+
const bc = cmd.browser_context orelse return error.BrowserContextNotLoaded;
97+
98+
var parents: std.ArrayListUnmanaged(*parser.Node) = .{};
99+
for (nodes) |_n| {
100+
var n = _n;
101+
while (true) {
102+
const p = try parser.nodeParentNode(n) orelse break;
103+
// If the parent exists in he registry, don't send the event.
104+
// In this case we stop browsing the tree, b/c parents must have
105+
// been sent already.
106+
if (bc.node_registry.lookup_by_node.contains(p)) {
107+
break;
108+
}
109+
try parents.append(arena, p);
110+
111+
n = p;
112+
}
113+
}
114+
115+
const plen = parents.items.len;
116+
if (plen == 0) return;
117+
118+
var i: usize = plen;
119+
while (i > 0) {
120+
i -= 1;
121+
const n = parents.items[i];
122+
// If the parent exists in he registry, don't send the event.
123+
// Indeed the parent can be twice in the array.
124+
if (bc.node_registry.lookup_by_node.contains(n)) {
125+
continue;
126+
}
127+
128+
// If the node has no parent, it's the root node.
129+
// We don't dispatch event for it because we assume the root node is
130+
// dispatched via the DOM.getDocument command.
131+
const p = try parser.nodeParentNode(n) orelse break;
132+
// Register the node.
133+
const node = try bc.node_registry.register(n);
134+
// Retrieve the parent from the registry.
135+
const parent_node = bc.node_registry.lookup_by_node.get(p) orelse unreachable;
136+
137+
try cmd.sendEvent("DOM.setChildNodes", .{
138+
.parentId = parent_node.id,
139+
.nodes = .{bc.nodeWriter(node, .{})},
140+
}, .{
141+
.session_id = bc.session_id.?,
142+
});
143+
}
144+
145+
// now dispatch the event for the node list.
146+
for (nodes) |n| {
147+
const node = bc.node_registry.lookup_by_node.get(n) orelse unreachable;
148+
const p = try parser.nodeParentNode(n) orelse continue;
149+
// Retrieve the parent from the registry.
150+
const parent_node = bc.node_registry.lookup_by_node.get(p) orelse unreachable;
151+
152+
try cmd.sendEvent("DOM.setChildNodes", .{
153+
.parentId = parent_node.id,
154+
.nodes = .{bc.nodeWriter(node, .{})},
155+
}, .{
156+
.session_id = bc.session_id.?,
157+
});
158+
}
159+
}
160+
104161
// https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-discardSearchResults
105162
fn discardSearchResults(cmd: anytype) !void {
106163
const params = (try cmd.params(struct {

0 commit comments

Comments
 (0)