From 5b2279ba1689169d8e3c98fc3d98d454cc4d9f1d Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 9 Sep 2026 11:39:15 +0800 Subject: [PATCH] webapi: improve indexing / enumerable of various collections Inspired by https://github.com/lightpanda-io/browser/pull/3454 which added the presence check for DOMStringMap, this adds the check to a number of other collections (PluginArray, HTMLAllCollection, ...). It also adds custom element reactions on indexed properties (previously only existing for named index properties). Finally, DOMStringMap now correctly handle numeric (or number-looking) indexes. --- src/browser/js/bridge.zig | 26 +++++ .../collections/html_all_collection.html | 22 +++++ src/browser/tests/element/attributes.html | 42 ++++++++ src/browser/tests/element/dataset.html | 98 +++++++++++++++++++ src/browser/tests/element/html/form.html | 28 ++++++ src/browser/tests/element/html/select.html | 22 +++++ src/browser/tests/navigator/navigator.html | 10 ++ src/browser/webapi/PluginArray.zig | 22 +++-- .../webapi/collections/HTMLAllCollection.zig | 25 +++-- .../HTMLFormControlsCollection.zig | 56 ++++++++--- .../collections/HTMLOptionsCollection.zig | 10 +- src/browser/webapi/element/Attribute.zig | 44 +++++---- src/browser/webapi/element/DOMStringMap.zig | 24 +++++ 13 files changed, 380 insertions(+), 49 deletions(-) diff --git a/src/browser/js/bridge.zig b/src/browser/js/bridge.zig index d6c4f12b6..0fae5bd58 100644 --- a/src/browser/js/bridge.zig +++ b/src/browser/js/bridge.zig @@ -300,6 +300,8 @@ pub const Indexed = struct { const Opts = struct { as_typed_array: bool = false, null_as_undefined: bool = false, + // Only applies to setter and deleter; getters don't mutate. + ce_reactions: bool = false, }; fn init(comptime T: type, comptime getter: anytype, setter: anytype, deleter: anytype, query: anytype, definer: anytype, comptime enumerator: anytype, comptime opts: Opts) Indexed { @@ -346,6 +348,18 @@ pub const Indexed = struct { } defer caller.deinit(); + const ce_frame: ?*Frame = if (comptime opts.ce_reactions) switch (caller.local.ctx.global) { + .frame => |frame| frame, + .worker => null, + } else null; + var ce_checkpoint: usize = undefined; + if (comptime opts.ce_reactions) { + if (ce_frame) |frame| ce_checkpoint = frame._ce_reactions.push(); + } + defer if (comptime opts.ce_reactions) { + if (ce_frame) |frame| frame._ce_reactions.popAndInvoke(ce_checkpoint, frame); + }; + return caller.setIndex(T, setter, idx, c_value.?, handle.?, .{ .as_typed_array = opts.as_typed_array, .null_as_undefined = opts.null_as_undefined, @@ -364,6 +378,18 @@ pub const Indexed = struct { } defer caller.deinit(); + const ce_frame: ?*Frame = if (comptime opts.ce_reactions) switch (caller.local.ctx.global) { + .frame => |frame| frame, + .worker => null, + } else null; + var ce_checkpoint: usize = undefined; + if (comptime opts.ce_reactions) { + if (ce_frame) |frame| ce_checkpoint = frame._ce_reactions.push(); + } + defer if (comptime opts.ce_reactions) { + if (ce_frame) |frame| frame._ce_reactions.popAndInvoke(ce_checkpoint, frame); + }; + return caller.deleteOrDefineIndex(T, deleter, idx, handle.?, .{ .as_typed_array = opts.as_typed_array, .null_as_undefined = opts.null_as_undefined, diff --git a/src/browser/tests/collections/html_all_collection.html b/src/browser/tests/collections/html_all_collection.html index 62bb4138c..87993069f 100644 --- a/src/browser/tests/collections/html_all_collection.html +++ b/src/browser/tests/collections/html_all_collection.html @@ -103,3 +103,25 @@ testing.expectEqual(false, !!document.all); } + + diff --git a/src/browser/tests/element/attributes.html b/src/browser/tests/element/attributes.html index 68652e5ef..384f3e489 100644 --- a/src/browser/tests/element/attributes.html +++ b/src/browser/tests/element/attributes.html @@ -2,6 +2,7 @@
+
+ + + + diff --git a/src/browser/tests/element/dataset.html b/src/browser/tests/element/dataset.html index 3df34585b..552e4af1f 100644 --- a/src/browser/tests/element/dataset.html +++ b/src/browser/tests/element/dataset.html @@ -121,6 +121,104 @@ } + + + + + + + + + + diff --git a/src/browser/tests/element/html/select.html b/src/browser/tests/element/html/select.html index 6d36c8b76..2de2b0dc5 100644 --- a/src/browser/tests/element/html/select.html +++ b/src/browser/tests/element/html/select.html @@ -7,6 +7,11 @@ + +