browser: centralize node interaction logic

Extracts click, fill, and scroll logic from CDP and MCP domains into a
new dedicated actions module to reduce code duplication.
This commit is contained in:
Adrià Arrufat
2026-03-16 14:22:15 +09:00
parent 1972142703
commit 32f450f803
4 changed files with 125 additions and 118 deletions

View File

@@ -165,18 +165,10 @@ fn clickNode(cmd: anytype) !void {
const input_node_id = params.nodeId orelse params.backendNodeId orelse return error.InvalidParam;
const node = bc.node_registry.lookup_by_id.get(input_node_id) orelse return error.InvalidNodeId;
if (node.dom.is(DOMNode.Element)) |el| {
if (el.is(DOMNode.Element.Html)) |html_el| {
html_el.click(page) catch |err| {
log.err(.cdp, "click failed", .{ .err = err });
return error.InternalError;
};
} else {
return error.InvalidParam;
}
} else {
return error.InvalidParam;
}
lp.actions.clickNode(node.dom, page) catch |err| {
if (err == error.InvalidNodeType) return error.InvalidParam;
return error.InternalError;
};
return cmd.sendResult(.{}, .{});
}
@@ -195,35 +187,10 @@ fn fillNode(cmd: anytype) !void {
const input_node_id = params.nodeId orelse params.backendNodeId orelse return error.InvalidParam;
const node = bc.node_registry.lookup_by_id.get(input_node_id) orelse return error.InvalidNodeId;
if (node.dom.is(DOMNode.Element)) |el| {
if (el.is(DOMNode.Element.Html.Input)) |input| {
input.setValue(params.text, page) catch |err| {
log.err(.cdp, "fill input failed", .{ .err = err });
return error.InternalError;
};
} else if (el.is(DOMNode.Element.Html.TextArea)) |textarea| {
textarea.setValue(params.text, page) catch |err| {
log.err(.cdp, "fill textarea failed", .{ .err = err });
return error.InternalError;
};
} else if (el.is(DOMNode.Element.Html.Select)) |select| {
select.setValue(params.text, page) catch |err| {
log.err(.cdp, "fill select failed", .{ .err = err });
return error.InternalError;
};
} else {
return error.InvalidParam;
}
const Event = @import("../../browser/webapi/Event.zig");
const input_evt = try Event.initTrusted(comptime lp.String.wrap("input"), .{ .bubbles = true }, page);
_ = page._event_manager.dispatch(el.asEventTarget(), input_evt) catch {};
const change_evt = try Event.initTrusted(comptime lp.String.wrap("change"), .{ .bubbles = true }, page);
_ = page._event_manager.dispatch(el.asEventTarget(), change_evt) catch {};
} else {
return error.InvalidParam;
}
lp.actions.fillNode(node.dom, params.text, page) catch |err| {
if (err == error.InvalidNodeType) return error.InvalidParam;
return error.InternalError;
};
return cmd.sendResult(.{}, .{});
}
@@ -245,33 +212,19 @@ fn scrollNode(cmd: anytype) !void {
const input_node_id = params.nodeId orelse params.backendNodeId;
var target_node: ?*DOMNode = null;
if (input_node_id) |node_id| {
const node = bc.node_registry.lookup_by_id.get(node_id) orelse return error.InvalidNodeId;
if (node.dom.is(DOMNode.Element)) |el| {
if (params.x != null) {
el.setScrollLeft(x, page) catch {};
}
if (params.y != null) {
el.setScrollTop(y, page) catch {};
}
const Event = @import("../../browser/webapi/Event.zig");
const scroll_evt = try Event.initTrusted(comptime lp.String.wrap("scroll"), .{ .bubbles = true }, page);
_ = page._event_manager.dispatch(el.asEventTarget(), scroll_evt) catch {};
} else {
return error.InvalidParam;
}
} else {
page.window.scrollTo(.{ .x = x }, y, page) catch |err| {
log.err(.cdp, "scroll failed", .{ .err = err });
return error.InternalError;
};
target_node = node.dom;
}
lp.actions.scrollNode(target_node, x, y, page) catch |err| {
if (err == error.InvalidNodeType) return error.InvalidParam;
return error.InternalError;
};
return cmd.sendResult(.{}, .{});
}
const testing = @import("../testing.zig");
test "cdp.lp: getMarkdown" {
var ctx = testing.context();