diff --git a/src/browser/Frame.zig b/src/browser/Frame.zig
index e55af9316..3631ffb8f 100644
--- a/src/browser/Frame.zig
+++ b/src/browser/Frame.zig
@@ -134,6 +134,7 @@ _element_computed_styles: Element.StyleLookup = .empty,
_element_datasets: Element.DatasetLookup = .empty,
_element_class_lists: Element.ClassListLookup = .empty,
_element_rel_lists: Element.RelListLookup = .empty,
+_element_token_lists: Element.TokenListLookup = .empty,
_element_shadow_roots: Element.ShadowRootLookup = .empty,
_node_owner_documents: Node.OwnerDocumentLookup = .empty,
_element_scroll_positions: Element.ScrollPositionLookup = .empty,
diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig
index 42150597b..9edf06296 100644
--- a/src/browser/webapi/Element.zig
+++ b/src/browser/webapi/Element.zig
@@ -885,6 +885,23 @@ pub fn getRelList(self: *Element, frame: *Frame) !*collections.DOMTokenList {
return gop.value_ptr.*;
}
+// The other DOMTokenList-reflected attributes (class and rel have dedicated
+// lookups above).
+pub const TokenListAttribute = enum { sizes, sandbox, @"for" };
+pub const TokenListKey = struct { element: *Element, attribute: TokenListAttribute };
+pub const TokenListLookup = std.AutoHashMapUnmanaged(TokenListKey, *collections.DOMTokenList);
+
+pub fn getTokenList(self: *Element, comptime attribute: TokenListAttribute, frame: *Frame) !*collections.DOMTokenList {
+ const gop = try frame._element_token_lists.getOrPut(frame.arena, .{ .element = self, .attribute = attribute });
+ if (!gop.found_existing) {
+ gop.value_ptr.* = try frame._factory.create(collections.DOMTokenList{
+ ._element = self,
+ ._attribute_name = comptime .wrap(@tagName(attribute)),
+ });
+ }
+ return gop.value_ptr.*;
+}
+
pub fn getDataset(self: *Element, frame: *Frame) !*DOMStringMap {
const gop = try frame._element_datasets.getOrPut(frame.arena, self);
if (!gop.found_existing) {
diff --git a/src/browser/webapi/element/html/Area.zig b/src/browser/webapi/element/html/Area.zig
index 0c9c821bc..edf6a96ef 100644
--- a/src/browser/webapi/element/html/Area.zig
+++ b/src/browser/webapi/element/html/Area.zig
@@ -290,12 +290,11 @@ pub const JsApi = struct {
pub const referrerPolicy = bridge.accessor(Area.getReferrerPolicy, Area.setReferrerPolicy, .{ .ce_reactions = true });
pub const relList = bridge.accessor(_getRelList, null, .{ .null_as_undefined = true });
pub const toString = bridge.function(Area.getHref, .{});
-
+ pub const relList = bridge.accessor(_getRelList, null, .{ .null_as_undefined = true });
fn _getRelList(self: *Area, frame: *Frame) !?*@import("../../collections.zig").DOMTokenList {
const element = self.asElement();
- // relList is only valid for HTML and SVG elements
- const namespace = element._namespace;
- if (namespace != .html and namespace != .svg) {
+ // relList is only valid for HTML elements
+ if (element._namespace != .html) {
return null;
}
return element.getRelList(frame);
diff --git a/src/browser/webapi/element/html/IFrame.zig b/src/browser/webapi/element/html/IFrame.zig
index a5163c8e4..5e2153b76 100644
--- a/src/browser/webapi/element/html/IFrame.zig
+++ b/src/browser/webapi/element/html/IFrame.zig
@@ -93,6 +93,15 @@ pub const JsApi = struct {
pub const name = bridge.accessor(IFrame.getName, IFrame.setName, .{ .ce_reactions = true });
pub const contentWindow = bridge.accessor(IFrame.getContentWindow, null, .{});
pub const contentDocument = bridge.accessor(IFrame.getContentDocument, null, .{});
+ pub const sandbox = bridge.accessor(_getSandbox, null, .{ .null_as_undefined = true });
+
+ fn _getSandbox(self: *IFrame, frame: *Frame) !?*@import("../../collections.zig").DOMTokenList {
+ const element = self.asElement();
+ if (element._namespace != .html) {
+ return null;
+ }
+ return element.getTokenList(.sandbox, frame);
+ }
};
pub const Build = struct {
diff --git a/src/browser/webapi/element/html/Link.zig b/src/browser/webapi/element/html/Link.zig
index 7eb2190f5..06eee926d 100644
--- a/src/browser/webapi/element/html/Link.zig
+++ b/src/browser/webapi/element/html/Link.zig
@@ -256,6 +256,15 @@ pub const JsApi = struct {
pub const rev = bridge.accessor(Link.getRev, Link.setRev, .{ .ce_reactions = true });
pub const target = bridge.accessor(Link.getTarget, Link.setTarget, .{ .ce_reactions = true });
pub const relList = bridge.accessor(_getRelList, null, .{ .null_as_undefined = true });
+ pub const sizes = bridge.accessor(_getSizes, null, .{ .null_as_undefined = true });
+
+ fn _getSizes(self: *Link, frame: *Frame) !?*@import("../../collections.zig").DOMTokenList {
+ const element = self.asElement();
+ if (element._namespace != .html) {
+ return null;
+ }
+ return element.getTokenList(.sizes, frame);
+ }
fn _getRelList(self: *Link, frame: *Frame) !?*@import("../../collections.zig").DOMTokenList {
const element = self.asElement();
diff --git a/src/browser/webapi/element/html/Output.zig b/src/browser/webapi/element/html/Output.zig
index 207e03a4b..96240077e 100644
--- a/src/browser/webapi/element/html/Output.zig
+++ b/src/browser/webapi/element/html/Output.zig
@@ -29,4 +29,13 @@ pub const JsApi = struct {
};
pub const labels = bridge.accessor(Output.getLabels, null, .{});
+ pub const htmlFor = bridge.accessor(_getHtmlFor, null, .{ .null_as_undefined = true });
+
+ fn _getHtmlFor(self: *Output, frame: *Frame) !?*@import("../../collections.zig").DOMTokenList {
+ const element = self.asElement();
+ if (element._namespace != .html) {
+ return null;
+ }
+ return element.getTokenList(.@"for", frame);
+ }
};