fix: pass allocator as first parameter in forms.zig

This commit is contained in:
Adrià Arrufat
2026-03-23 15:27:49 +09:00
parent a6e801be59
commit c3a2318eca
3 changed files with 23 additions and 12 deletions

View File

@@ -137,8 +137,8 @@ pub const FormInfo = struct {
/// Collect all forms and their fields under `root`. /// Collect all forms and their fields under `root`.
pub fn collectForms( pub fn collectForms(
root: *Node,
arena: Allocator, arena: Allocator,
root: *Node,
page: *Page, page: *Page,
) ![]FormInfo { ) ![]FormInfo {
var forms: std.ArrayList(FormInfo) = .empty; var forms: std.ArrayList(FormInfo) = .empty;
@@ -150,7 +150,7 @@ pub fn collectForms(
const form_el = el.is(Element.Html.Form) orelse continue; const form_el = el.is(Element.Html.Form) orelse continue;
const fields = try collectFormFields(node, arena, page); const fields = try collectFormFields(arena, node, page);
if (fields.len == 0) continue; if (fields.len == 0) continue;
const action_attr = el.getAttributeSafe(comptime .wrap("action")); const action_attr = el.getAttributeSafe(comptime .wrap("action"));
@@ -168,8 +168,8 @@ pub fn collectForms(
} }
fn collectFormFields( fn collectFormFields(
form_node: *Node,
arena: Allocator, arena: Allocator,
form_node: *Node,
page: *Page, page: *Page,
) ![]FormField { ) ![]FormField {
var fields: std.ArrayList(FormField) = .empty; var fields: std.ArrayList(FormField) = .empty;
@@ -180,7 +180,7 @@ fn collectFormFields(
switch (el.getTag()) { switch (el.getTag()) {
.input => { .input => {
const input = el.as(Element.Html.Input); const input = el.is(Element.Html.Input) orelse continue;
if (input._input_type == .hidden) continue; if (input._input_type == .hidden) continue;
if (input._input_type == .submit or input._input_type == .button or input._input_type == .image) continue; if (input._input_type == .submit or input._input_type == .button or input._input_type == .image) continue;
@@ -196,7 +196,7 @@ fn collectFormFields(
}); });
}, },
.textarea => { .textarea => {
const textarea = el.as(Element.Html.TextArea); const textarea = el.is(Element.Html.TextArea) orelse continue;
try fields.append(arena, .{ try fields.append(arena, .{
.node = node, .node = node,
@@ -210,9 +210,9 @@ fn collectFormFields(
}); });
}, },
.select => { .select => {
const select = el.as(Element.Html.Select); const select = el.is(Element.Html.Select) orelse continue;
const options = try collectSelectOptions(node, arena, page); const options = try collectSelectOptions(arena, node, page);
try fields.append(arena, .{ try fields.append(arena, .{
.node = node, .node = node,
@@ -233,8 +233,8 @@ fn collectFormFields(
} }
fn collectSelectOptions( fn collectSelectOptions(
select_node: *Node,
arena: Allocator, arena: Allocator,
select_node: *Node,
page: *Page, page: *Page,
) ![]SelectOption { ) ![]SelectOption {
var options: std.ArrayList(SelectOption) = .empty; var options: std.ArrayList(SelectOption) = .empty;
@@ -258,16 +258,17 @@ const testing = @import("../testing.zig");
fn testForms(html: []const u8) ![]FormInfo { fn testForms(html: []const u8) ![]FormInfo {
const page = try testing.test_session.createPage(); const page = try testing.test_session.createPage();
defer testing.test_session.removePage();
const doc = page.window._document; const doc = page.window._document;
const div = try doc.createElement("div", null, page); const div = try doc.createElement("div", null, page);
try page.parseHtmlAsChildren(div.asNode(), html); try page.parseHtmlAsChildren(div.asNode(), html);
return collectForms(div.asNode(), page.call_arena, page); return collectForms(page.call_arena, div.asNode(), page);
} }
test "browser.forms: login form" { test "browser.forms: login form" {
defer testing.reset();
defer testing.test_session.removePage();
const forms = try testForms( const forms = try testForms(
\\<form action="/login" method="POST"> \\<form action="/login" method="POST">
\\ <input type="email" name="email" required placeholder="Email"> \\ <input type="email" name="email" required placeholder="Email">
@@ -286,6 +287,8 @@ test "browser.forms: login form" {
} }
test "browser.forms: form with select" { test "browser.forms: form with select" {
defer testing.reset();
defer testing.test_session.removePage();
const forms = try testForms( const forms = try testForms(
\\<form> \\<form>
\\ <select name="color"> \\ <select name="color">
@@ -303,6 +306,8 @@ test "browser.forms: form with select" {
} }
test "browser.forms: form with textarea" { test "browser.forms: form with textarea" {
defer testing.reset();
defer testing.test_session.removePage();
const forms = try testForms( const forms = try testForms(
\\<form method="POST"> \\<form method="POST">
\\ <textarea name="message" placeholder="Your message"></textarea> \\ <textarea name="message" placeholder="Your message"></textarea>
@@ -315,6 +320,8 @@ test "browser.forms: form with textarea" {
} }
test "browser.forms: empty form skipped" { test "browser.forms: empty form skipped" {
defer testing.reset();
defer testing.test_session.removePage();
const forms = try testForms( const forms = try testForms(
\\<form action="/empty"> \\<form action="/empty">
\\ <p>No fields here</p> \\ <p>No fields here</p>
@@ -324,6 +331,8 @@ test "browser.forms: empty form skipped" {
} }
test "browser.forms: hidden inputs excluded" { test "browser.forms: hidden inputs excluded" {
defer testing.reset();
defer testing.test_session.removePage();
const forms = try testForms( const forms = try testForms(
\\<form> \\<form>
\\ <input type="hidden" name="csrf" value="token123"> \\ <input type="hidden" name="csrf" value="token123">
@@ -336,6 +345,8 @@ test "browser.forms: hidden inputs excluded" {
} }
test "browser.forms: multiple forms" { test "browser.forms: multiple forms" {
defer testing.reset();
defer testing.test_session.removePage();
const forms = try testForms( const forms = try testForms(
\\<form action="/search" method="GET"> \\<form action="/search" method="GET">
\\ <input type="text" name="q" placeholder="Search"> \\ <input type="text" name="q" placeholder="Search">

View File

@@ -167,8 +167,8 @@ fn detectForms(cmd: anytype) !void {
const page = bc.session.currentPage() orelse return error.PageNotLoaded; const page = bc.session.currentPage() orelse return error.PageNotLoaded;
const forms_data = try lp.forms.collectForms( const forms_data = try lp.forms.collectForms(
page.document.asNode(),
cmd.arena, cmd.arena,
page.document.asNode(),
page, page,
); );

View File

@@ -465,7 +465,7 @@ fn handleDetectForms(server: *Server, arena: std.mem.Allocator, id: std.json.Val
return server.sendError(id, .PageNotLoaded, "Page not loaded"); return server.sendError(id, .PageNotLoaded, "Page not loaded");
}; };
const forms_data = lp.forms.collectForms(page.document.asNode(), arena, page) catch |err| { const forms_data = lp.forms.collectForms(arena, page.document.asNode(), page) catch |err| {
log.err(.mcp, "form collection failed", .{ .err = err }); log.err(.mcp, "form collection failed", .{ .err = err });
return server.sendError(id, .InternalError, "Failed to collect forms"); return server.sendError(id, .InternalError, "Failed to collect forms");
}; };