Merge pull request #782 from lightpanda-io/form_support_dynamic_elements

Use css.querySelectorAll to find form elements
This commit is contained in:
Karl Seguin
2025-06-17 08:07:30 +08:00
committed by GitHub

View File

@@ -115,17 +115,24 @@ const EntryIterable = iterator.Iterable(kv.EntryIterator, "FormDataEntryIterator
// TODO: handle disabled fieldsets // TODO: handle disabled fieldsets
fn collectForm(form: *parser.Form, submitter_: ?*parser.ElementHTML, page: *Page) !kv.List { fn collectForm(form: *parser.Form, submitter_: ?*parser.ElementHTML, page: *Page) !kv.List {
const arena = page.arena; const arena = page.arena;
const collection = try parser.formGetCollection(form);
const len = try parser.htmlCollectionGetLength(collection); // Don't use libdom's formGetCollection (aka dom_html_form_element_get_elements)
// It doesn't work with dynamically added elements, because their form
// property doesn't get set. We should fix that.
// However, even once fixed, there are other form-collection features we
// probably want to implement (like disabled fieldsets), so we might want
// to stick with our own walker even if fix libdom to properly support
// dynamically added elements.
const node_list = try @import("../dom/css.zig").querySelectorAll(arena, @alignCast(@ptrCast(form)), "input,select,button,textarea");
const nodes = node_list.nodes.items;
var entries: kv.List = .{}; var entries: kv.List = .{};
try entries.ensureTotalCapacity(arena, len); try entries.ensureTotalCapacity(arena, nodes.len);
var submitter_included = false; var submitter_included = false;
const submitter_name_ = try getSubmitterName(submitter_); const submitter_name_ = try getSubmitterName(submitter_);
for (0..len) |i| { for (nodes) |node| {
const node = try parser.htmlCollectionItem(collection, @intCast(i));
const element = parser.nodeToElement(node); const element = parser.nodeToElement(node);
// must have a name // must have a name
@@ -181,10 +188,7 @@ fn collectForm(form: *parser.Form, submitter_: ?*parser.ElementHTML, page: *Page
submitter_included = true; submitter_included = true;
} }
}, },
else => { else => unreachable,
log.warn(.web_api, "unsupported form element", .{ .tag = @tagName(tag) });
continue;
},
} }
} }
@@ -297,6 +301,7 @@ test "Browser.FormData" {
\\ <input type=submit name=s2 value=s2-v> \\ <input type=submit name=s2 value=s2-v>
\\ <input type=image name=i1 value=i1-v> \\ <input type=image name=i1 value=i1-v>
\\ </form> \\ </form>
\\ <input type=text name=abc value=123 form=form1>
}); });
defer runner.deinit(); defer runner.deinit();
@@ -356,6 +361,8 @@ test "Browser.FormData" {
try runner.testCases(&.{ try runner.testCases(&.{
.{ "let form1 = document.getElementById('form1')", null }, .{ "let form1 = document.getElementById('form1')", null },
.{ "let input = document.createElement('input');", null },
.{ "input.name = 'dyn'; input.value= 'dyn-v'; form1.appendChild(input);", null },
.{ "let submit1 = document.getElementById('s1')", null }, .{ "let submit1 = document.getElementById('s1')", null },
.{ "let f2 = new FormData(form1, submit1)", null }, .{ "let f2 = new FormData(form1, submit1)", null },
.{ "acc = '';", null }, .{ "acc = '';", null },
@@ -378,6 +385,7 @@ test "Browser.FormData" {
\\mlt-2=water \\mlt-2=water
\\mlt-2=tea \\mlt-2=tea
\\s1=s1-v \\s1=s1-v
\\dyn=dyn-v
}, },
}, .{}); }, .{});
} }