From 078eccea2d107f06b257b9334e733d79966b1917 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 02:29:12 +0300 Subject: [PATCH 01/10] update doc comment --- src/browser/Page.zig | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/browser/Page.zig b/src/browser/Page.zig index e769f9a5..f5149f9e 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -104,14 +104,20 @@ _element_assigned_slots: Element.AssignedSlotLookup = .{}, /// Lazily-created inline event listeners (or listeners provided as attributes). /// Avoids bloating all elements with extra function fields for rare usage. /// -/// Use this when a listener provided like these: +/// Use this when a listener provided like this: +/// +/// ```js +/// img.onload = () => { ... }; +/// ``` +/// +/// Its also used as cache for such cases after lazy evaluation: /// /// ```html /// /// ``` /// /// ```js -/// img.onload = () => { ... }; +/// img.setAttribute("onload", "(() => { ... })()"); /// ``` _element_attr_listeners: Element.AttrListenerLookup = .{}, From 8a995fc515c47693116f235c562c96044f6e665e Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 02:29:41 +0300 Subject: [PATCH 02/10] `createLookupKey` -> `calcAttrListenerKey` --- src/browser/webapi/Element.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index d0e779a9..ab44ac05 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -163,12 +163,12 @@ pub fn calcAttrListenerKey(self: *Element, event_type: KnownListener) AttrListen // its size and alignment, though. const target = self.asEventTarget(); // Check if we have 3 bits available from alignment of 8. - lp.assert(@alignOf(@TypeOf(target)) == 8, "createLookupKey: incorrect alignment", .{ + lp.assert(@alignOf(@TypeOf(target)) == 8, "calcAttrListenerKey: incorrect alignment", .{ .event_target_alignment = @alignOf(@TypeOf(target)), }); const ptr = @intFromPtr(target) >> 3; - lp.assert(ptr < (1 << 57), "createLookupKey: pointer overflow", .{ .ptr = ptr }); + lp.assert(ptr < (1 << 57), "calcAttrListenerKey: pointer overflow", .{ .ptr = ptr }); return ptr | (@as(u64, @intFromEnum(event_type)) << 57); } From cc51cd44762a96ceee6b1d42f9168e15f34cc346 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 02:30:28 +0300 Subject: [PATCH 03/10] remove eager event listener parsing --- src/browser/Page.zig | 230 ------------------------------------------- 1 file changed, 230 deletions(-) diff --git a/src/browser/Page.zig b/src/browser/Page.zig index f5149f9e..abdb7845 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -2278,236 +2278,6 @@ fn populateElementAttributes(self: *Page, element: *Element, list: anytype) !voi } var attributes = try element.createAttributeList(self); while (list.next()) |attr| { - // Event handlers can be provided like attributes; here we check if there's such. - const name = attr.name.local; - lp.assert(name.len != 0, "populateElementAttributes: 0-length attr name", .{ .attr = attr }); - // Idea here is to make this check as cheap as possible. - const has_on_prefix = @as(u16, @bitCast([2]u8{ name.ptr[0], name.ptr[1 % name.len] })) == asUint("on"); - // We may have found an event handler. - if (has_on_prefix) { - // Must be usable as function. - const func = self.js.stringToPersistedFunction(attr.value.slice()) catch continue; - - // Longest known listener kind is 32 bytes long. - const remaining: u6 = @truncate(name.len -| 2); - const unsafe = name.ptr + 2; - const Vec16x8 = @Vector(16, u8); - const Vec32x8 = @Vector(32, u8); - - switch (remaining) { - 3 => if (@as(u24, @bitCast(unsafe[0..3].*)) == asUint("cut")) { - try self.setAttrListener(element, .cut, func); - }, - 4 => switch (@as(u32, @bitCast(unsafe[0..4].*))) { - asUint("blur") => try self.setAttrListener(element, .blur, func), - asUint("copy") => try self.setAttrListener(element, .copy, func), - asUint("drag") => try self.setAttrListener(element, .drag, func), - asUint("drop") => try self.setAttrListener(element, .drop, func), - asUint("load") => try self.setAttrListener(element, .load, func), - asUint("play") => try self.setAttrListener(element, .play, func), - else => {}, - }, - 5 => switch (@as(u40, @bitCast(unsafe[0..5].*))) { - asUint("abort") => try self.setAttrListener(element, .abort, func), - asUint("click") => try self.setAttrListener(element, .click, func), - asUint("close") => try self.setAttrListener(element, .close, func), - asUint("ended") => try self.setAttrListener(element, .ended, func), - asUint("error") => try self.setAttrListener(element, .@"error", func), - asUint("focus") => try self.setAttrListener(element, .focus, func), - asUint("input") => try self.setAttrListener(element, .input, func), - asUint("keyup") => try self.setAttrListener(element, .keyup, func), - asUint("paste") => try self.setAttrListener(element, .paste, func), - asUint("pause") => try self.setAttrListener(element, .pause, func), - asUint("reset") => try self.setAttrListener(element, .reset, func), - asUint("wheel") => try self.setAttrListener(element, .wheel, func), - else => {}, - }, - 6 => switch (@as(u48, @bitCast(unsafe[0..6].*))) { - asUint("cancel") => try self.setAttrListener(element, .cancel, func), - asUint("change") => try self.setAttrListener(element, .change, func), - asUint("resize") => try self.setAttrListener(element, .resize, func), - asUint("scroll") => try self.setAttrListener(element, .scroll, func), - asUint("seeked") => try self.setAttrListener(element, .seeked, func), - asUint("select") => try self.setAttrListener(element, .select, func), - asUint("submit") => try self.setAttrListener(element, .submit, func), - asUint("toggle") => try self.setAttrListener(element, .toggle, func), - else => {}, - }, - 7 => switch (@as(u56, @bitCast(unsafe[0..7].*))) { - asUint("canplay") => try self.setAttrListener(element, .canplay, func), - asUint("command") => try self.setAttrListener(element, .command, func), - asUint("dragend") => try self.setAttrListener(element, .dragend, func), - asUint("emptied") => try self.setAttrListener(element, .emptied, func), - asUint("invalid") => try self.setAttrListener(element, .invalid, func), - asUint("keydown") => try self.setAttrListener(element, .keydown, func), - asUint("mouseup") => try self.setAttrListener(element, .mouseup, func), - asUint("playing") => try self.setAttrListener(element, .playing, func), - asUint("seeking") => try self.setAttrListener(element, .seeking, func), - asUint("stalled") => try self.setAttrListener(element, .stalled, func), - asUint("suspend") => try self.setAttrListener(element, .@"suspend", func), - asUint("waiting") => try self.setAttrListener(element, .waiting, func), - else => {}, - }, - 8 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("auxclick") => try self.setAttrListener(element, .auxclick, func), - asUint("dblclick") => try self.setAttrListener(element, .dblclick, func), - asUint("dragexit") => try self.setAttrListener(element, .dragexit, func), - asUint("dragover") => try self.setAttrListener(element, .dragover, func), - asUint("formdata") => try self.setAttrListener(element, .formdata, func), - asUint("keypress") => try self.setAttrListener(element, .keypress, func), - asUint("mouseout") => try self.setAttrListener(element, .mouseout, func), - asUint("progress") => try self.setAttrListener(element, .progress, func), - else => {}, - }, - // Won't fit to 64-bit integer; we do 2 checks. - 9 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("cuechang") => if (unsafe[8] == 'e') try self.setAttrListener(element, .cuechange, func), - asUint("dragente") => if (unsafe[8] == 'r') try self.setAttrListener(element, .dragenter, func), - asUint("dragleav") => if (unsafe[8] == 'e') try self.setAttrListener(element, .dragleave, func), - asUint("dragstar") => if (unsafe[8] == 't') try self.setAttrListener(element, .dragstart, func), - asUint("loadstar") => if (unsafe[8] == 't') try self.setAttrListener(element, .loadstart, func), - asUint("mousedow") => if (unsafe[8] == 'n') try self.setAttrListener(element, .mousedown, func), - asUint("mousemov") => if (unsafe[8] == 'e') try self.setAttrListener(element, .mousemove, func), - asUint("mouseove") => if (unsafe[8] == 'r') try self.setAttrListener(element, .mouseover, func), - asUint("pointeru") => if (unsafe[8] == 'p') try self.setAttrListener(element, .pointerup, func), - asUint("scrollen") => if (unsafe[8] == 'd') try self.setAttrListener(element, .scrollend, func), - else => {}, - }, - 10 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("loadedda") => if (asUint("ta") == @as(u16, @bitCast(unsafe[8..10].*))) - try self.setAttrListener(element, .loadeddata, func), - asUint("pointero") => if (asUint("ut") == @as(u16, @bitCast(unsafe[8..10].*))) - try self.setAttrListener(element, .pointerout, func), - asUint("ratechan") => if (asUint("ge") == @as(u16, @bitCast(unsafe[8..10].*))) - try self.setAttrListener(element, .ratechange, func), - asUint("slotchan") => if (asUint("ge") == @as(u16, @bitCast(unsafe[8..10].*))) - try self.setAttrListener(element, .slotchange, func), - asUint("timeupda") => if (asUint("te") == @as(u16, @bitCast(unsafe[8..10].*))) - try self.setAttrListener(element, .timeupdate, func), - else => {}, - }, - 11 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("beforein") => if (asUint("put") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .beforeinput, func), - asUint("beforema") => if (asUint("tch") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .beforematch, func), - asUint("contextl") => if (asUint("ost") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .contextlost, func), - asUint("contextm") => if (asUint("enu") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .contextmenu, func), - asUint("pointerd") => if (asUint("own") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .pointerdown, func), - asUint("pointerm") => if (asUint("ove") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .pointermove, func), - asUint("pointero") => if (asUint("ver") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .pointerover, func), - asUint("selectst") => if (asUint("art") == @as(u24, @bitCast(unsafe[8..11].*))) - try self.setAttrListener(element, .selectstart, func), - else => {}, - }, - 12 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("animatio") => if (asUint("nend") == @as(u32, @bitCast(unsafe[8..12].*))) - try self.setAttrListener(element, .animationend, func), - asUint("beforeto") => if (asUint("ggle") == @as(u32, @bitCast(unsafe[8..12].*))) - try self.setAttrListener(element, .beforetoggle, func), - asUint("pointere") => if (asUint("nter") == @as(u32, @bitCast(unsafe[8..12].*))) - try self.setAttrListener(element, .pointerenter, func), - asUint("pointerl") => if (asUint("eave") == @as(u32, @bitCast(unsafe[8..12].*))) - try self.setAttrListener(element, .pointerleave, func), - asUint("volumech") => if (asUint("ange") == @as(u32, @bitCast(unsafe[8..12].*))) - try self.setAttrListener(element, .volumechange, func), - else => {}, - }, - 13 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("pointerc") => if (asUint("ancel") == @as(u40, @bitCast(unsafe[8..13].*))) - try self.setAttrListener(element, .pointercancel, func), - asUint("transiti") => switch (@as(u40, @bitCast(unsafe[8..13].*))) { - asUint("onend") => try self.setAttrListener(element, .transitionend, func), - asUint("onrun") => try self.setAttrListener(element, .transitionrun, func), - else => {}, - }, - else => {}, - }, - 14 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("animatio") => if (asUint("nstart") == @as(u48, @bitCast(unsafe[8..14].*))) - try self.setAttrListener(element, .animationstart, func), - asUint("canplayt") => if (asUint("hrough") == @as(u48, @bitCast(unsafe[8..14].*))) - try self.setAttrListener(element, .canplaythrough, func), - asUint("duration") => if (asUint("change") == @as(u48, @bitCast(unsafe[8..14].*))) - try self.setAttrListener(element, .durationchange, func), - asUint("loadedme") => if (asUint("tadata") == @as(u48, @bitCast(unsafe[8..14].*))) - try self.setAttrListener(element, .loadedmetadata, func), - else => {}, - }, - 15 => switch (@as(u64, @bitCast(unsafe[0..8].*))) { - asUint("animatio") => if (asUint("ncancel") == @as(u56, @bitCast(unsafe[8..15].*))) - try self.setAttrListener(element, .animationcancel, func), - asUint("contextr") => if (asUint("estored") == @as(u56, @bitCast(unsafe[8..15].*))) - try self.setAttrListener(element, .contextrestored, func), - asUint("fullscre") => if (asUint("enerror") == @as(u56, @bitCast(unsafe[8..15].*))) - try self.setAttrListener(element, .fullscreenerror, func), - asUint("selectio") => if (asUint("nchange") == @as(u56, @bitCast(unsafe[8..15].*))) - try self.setAttrListener(element, .selectionchange, func), - asUint("transiti") => if (asUint("onstart") == @as(u56, @bitCast(unsafe[8..15].*))) - try self.setAttrListener(element, .transitionstart, func), - else => {}, - }, - // Can't switch on vector types. - 16 => { - const as_vector: Vec16x8 = unsafe[0..16].*; - - if (@reduce(.And, as_vector == @as(Vec16x8, "fullscreenchange".*))) { - try self.setAttrListener(element, .fullscreenchange, func); - } else if (@reduce(.And, as_vector == @as(Vec16x8, "pointerrawupdate".*))) { - try self.setAttrListener(element, .pointerrawupdate, func); - } else if (@reduce(.And, as_vector == @as(Vec16x8, "transitioncancel".*))) { - try self.setAttrListener(element, .transitioncancel, func); - } - }, - 17 => { - const as_vector: Vec16x8 = unsafe[0..16].*; - - const dirty = @reduce(.And, as_vector == @as(Vec16x8, "gotpointercaptur".*)) and - unsafe[16] == 'e'; - if (dirty) { - try self.setAttrListener(element, .gotpointercapture, func); - } - }, - 18 => { - const as_vector: Vec16x8 = unsafe[0..16].*; - - const is_animationiteration = @reduce(.And, as_vector == @as(Vec16x8, "animationiterati".*)) and - asUint("on") == @as(u16, @bitCast(unsafe[16..18].*)); - if (is_animationiteration) { - try self.setAttrListener(element, .animationiteration, func); - } else { - const is_lostpointercapture = @reduce(.And, as_vector == @as(Vec16x8, "lostpointercaptu".*)) and - asUint("re") == @as(u16, @bitCast(unsafe[16..18].*)); - if (is_lostpointercapture) { - try self.setAttrListener(element, .lostpointercapture, func); - } - } - }, - 23 => { - const as_vector: Vec16x8 = unsafe[0..16].*; - - const dirty = @reduce(.And, as_vector == @as(Vec16x8, "securitypolicyvi".*)) and - asUint("olation") == @as(u56, @bitCast(unsafe[16..23].*)); - if (dirty) { - try self.setAttrListener(element, .securitypolicyviolation, func); - } - }, - 32 => { - const as_vector: Vec32x8 = unsafe[0..32].*; - - if (@reduce(.And, as_vector == @as(Vec32x8, "contentvisibilityautostatechange".*))) { - try self.setAttrListener(element, .contentvisibilityautostatechange, func); - } - }, - else => {}, - } - } - try attributes.putNew(attr.name.local.slice(), attr.value.slice(), self); } } From b96cb2142bb5db679094c7ea62b7b110fd50ae1a Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 02:31:16 +0300 Subject: [PATCH 04/10] add `getAttributeFunction` --- src/browser/webapi/element/Html.zig | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 3844275b..30d5db57 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -18,6 +18,7 @@ const std = @import("std"); const js = @import("../../js/js.zig"); +const log = @import("../../../log.zig"); const reflect = @import("../../reflect.zig"); const Page = @import("../../Page.zig"); @@ -332,6 +333,40 @@ pub fn click(self: *HtmlElement, page: *Page) !void { try page._event_manager.dispatch(self.asEventTarget(), event.asEvent()); } +fn getAttributeFunction( + self: *HtmlElement, + comptime listener_type: Element.KnownListener, + page: *Page, +) ?js.Function.Global { + const element = self.asElement(); + if (page.getAttrListener(element, listener_type)) |cached| { + return cached; + } + + const attr = element.getAttributeSafe(.wrap(@tagName(listener_type))) orelse return null; + const callback = page.js.stringToPersistedFunction(attr) catch |err| { + // Not a valid expression; log this to find out if its something we should be supporting. + log.warn(.unknown_prop, "Page.getAttrListener", .{ + .expression = attr, + .err = err, + }); + + return null; + }; + + page.setAttrListener(element, listener_type, callback) catch { + // This is fine :tm: We're out of memory for cache. + // I don't want to make all getters "!?" just because of this honestly. + log.warn(.app, "getAttributeFunction", .{ + .element = element, + .listener_type = listener_type, + .callback = callback, + }); + }; + + return callback; +} + pub fn setOnAbort(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { return page.setAttrListener(self.asElement(), .abort, callback); } From f903e4b2de844defddf6c50b81cc92bcd2ac1ae4 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 02:31:37 +0300 Subject: [PATCH 05/10] bunch of renaming --- src/browser/webapi/Element.zig | 190 +++++++------- src/browser/webapi/element/Html.zig | 380 ++++++++++++++-------------- 2 files changed, 285 insertions(+), 285 deletions(-) diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index ab44ac05..23da8d03 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -59,101 +59,101 @@ pub const AttrListenerLookup = std.AutoHashMapUnmanaged(AttrListenerKey, js.Func /// Enum of known event listeners; increasing the size of it (u7) /// can cause `AttrListenerKey` to behave incorrectly. pub const KnownListener = enum(u7) { - abort, - animationcancel, - animationend, - animationiteration, - animationstart, - auxclick, - beforeinput, - beforematch, - beforetoggle, - blur, - cancel, - canplay, - canplaythrough, - change, - click, - close, - command, - contentvisibilityautostatechange, - contextlost, - contextmenu, - contextrestored, - copy, - cuechange, - cut, - dblclick, - drag, - dragend, - dragenter, - dragexit, - dragleave, - dragover, - dragstart, - drop, - durationchange, - emptied, - ended, - @"error", - focus, - formdata, - fullscreenchange, - fullscreenerror, - gotpointercapture, - input, - invalid, - keydown, - keypress, - keyup, - load, - loadeddata, - loadedmetadata, - loadstart, - lostpointercapture, - mousedown, - mousemove, - mouseout, - mouseover, - mouseup, - paste, - pause, - play, - playing, - pointercancel, - pointerdown, - pointerenter, - pointerleave, - pointermove, - pointerout, - pointerover, - pointerrawupdate, - pointerup, - progress, - ratechange, - reset, - resize, - scroll, - scrollend, - securitypolicyviolation, - seeked, - seeking, - select, - selectionchange, - selectstart, - slotchange, - stalled, - submit, - @"suspend", - timeupdate, - toggle, - transitioncancel, - transitionend, - transitionrun, - transitionstart, - volumechange, - waiting, - wheel, + onabort, + onanimationcancel, + onanimationend, + onanimationiteration, + onanimationstart, + onauxclick, + onbeforeinput, + onbeforematch, + onbeforetoggle, + onblur, + oncancel, + oncanplay, + oncanplaythrough, + onchange, + onclick, + onclose, + oncommand, + oncontentvisibilityautostatechange, + oncontextlost, + oncontextmenu, + oncontextrestored, + oncopy, + oncuechange, + oncut, + ondblclick, + ondrag, + ondragend, + ondragenter, + ondragexit, + ondragleave, + ondragover, + ondragstart, + ondrop, + ondurationchange, + onemptied, + onended, + onerror, + onfocus, + onformdata, + onfullscreenchange, + onfullscreenerror, + ongotpointercapture, + oninput, + oninvalid, + onkeydown, + onkeypress, + onkeyup, + onload, + onloadeddata, + onloadedmetadata, + onloadstart, + onlostpointercapture, + onmousedown, + onmousemove, + onmouseout, + onmouseover, + onmouseup, + onpaste, + onpause, + onplay, + onplaying, + onpointercancel, + onpointerdown, + onpointerenter, + onpointerleave, + onpointermove, + onpointerout, + onpointerover, + onpointerrawupdate, + onpointerup, + onprogress, + onratechange, + onreset, + onresize, + onscroll, + onscrollend, + onsecuritypolicyviolation, + onseeked, + onseeking, + onselect, + onselectionchange, + onselectstart, + onslotchange, + onstalled, + onsubmit, + onsuspend, + ontimeupdate, + ontoggle, + ontransitioncancel, + ontransitionend, + ontransitionrun, + ontransitionstart, + onvolumechange, + onwaiting, + onwheel, }; /// Calculates a lookup key (`AttrListenerKey`) to use with `AttrListenerLookup` for an element. diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 30d5db57..0a887ac7 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -368,763 +368,763 @@ fn getAttributeFunction( } pub fn setOnAbort(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .abort, callback); + return page.setAttrListener(self.asElement(), .onabort, callback); } pub fn getOnAbort(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .abort); + return self.getAttributeFunction(.onabort, page); } pub fn setOnAnimationCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .animationcancel, callback); + return page.setAttrListener(self.asElement(), .onanimationcancel, callback); } pub fn getOnAnimationCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .animationcancel); + return self.getAttributeFunction(.onanimationcancel, page); } pub fn setOnAnimationEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .animationend, callback); + return page.setAttrListener(self.asElement(), .onanimationend, callback); } pub fn getOnAnimationEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .animationend); + return self.getAttributeFunction(.onanimationend, page); } pub fn setOnAnimationIteration(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .animationiteration, callback); + return page.setAttrListener(self.asElement(), .onanimationiteration, callback); } pub fn getOnAnimationIteration(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .animationiteration); + return self.getAttributeFunction(.onanimationiteration, page); } pub fn setOnAnimationStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .animationstart, callback); + return page.setAttrListener(self.asElement(), .onanimationstart, callback); } pub fn getOnAnimationStart(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .animationstart); + return self.getAttributeFunction(.onanimationstart, page); } pub fn setOnAuxClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .auxclick, callback); + return page.setAttrListener(self.asElement(), .onauxclick, callback); } pub fn getOnAuxClick(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .auxclick); + return self.getAttributeFunction(.onauxclick, page); } pub fn setOnBeforeInput(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .beforeinput, callback); + return page.setAttrListener(self.asElement(), .onbeforeinput, callback); } pub fn getOnBeforeInput(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .beforeinput); + return self.getAttributeFunction(.onbeforeinput, page); } pub fn setOnBeforeMatch(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .beforematch, callback); + return page.setAttrListener(self.asElement(), .onbeforematch, callback); } pub fn getOnBeforeMatch(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .beforematch); + return self.getAttributeFunction(.onbeforematch, page); } pub fn setOnBeforeToggle(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .beforetoggle, callback); + return page.setAttrListener(self.asElement(), .onbeforetoggle, callback); } pub fn getOnBeforeToggle(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .beforetoggle); + return self.getAttributeFunction(.onbeforetoggle, page); } pub fn setOnBlur(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .blur, callback); + return page.setAttrListener(self.asElement(), .onblur, callback); } pub fn getOnBlur(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .blur); + return self.getAttributeFunction(.onblur, page); } pub fn setOnCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .cancel, callback); + return page.setAttrListener(self.asElement(), .oncancel, callback); } pub fn getOnCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .cancel); + return self.getAttributeFunction(.oncancel, page); } pub fn setOnCanPlay(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .canplay, callback); + return page.setAttrListener(self.asElement(), .oncanplay, callback); } pub fn getOnCanPlay(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .canplay); + return self.getAttributeFunction(.oncanplay, page); } pub fn setOnCanPlayThrough(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .canplaythrough, callback); + return page.setAttrListener(self.asElement(), .oncanplaythrough, callback); } pub fn getOnCanPlayThrough(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .canplaythrough); + return self.getAttributeFunction(.oncanplaythrough, page); } pub fn setOnChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .change, callback); + return page.setAttrListener(self.asElement(), .onchange, callback); } pub fn getOnChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .change); + return self.getAttributeFunction(.onchange, page); } pub fn setOnClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .click, callback); + return page.setAttrListener(self.asElement(), .onclick, callback); } pub fn getOnClick(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .click); + return self.getAttributeFunction(.onclick, page); } pub fn setOnClose(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .close, callback); + return page.setAttrListener(self.asElement(), .onclose, callback); } pub fn getOnClose(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .close); + return self.getAttributeFunction(.onclose, page); } pub fn setOnCommand(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .command, callback); + return page.setAttrListener(self.asElement(), .oncommand, callback); } pub fn getOnCommand(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .command); + return self.getAttributeFunction(.oncommand, page); } pub fn setOnContentVisibilityAutoStateChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .contentvisibilityautostatechange, callback); + return page.setAttrListener(self.asElement(), .oncontentvisibilityautostatechange, callback); } pub fn getOnContentVisibilityAutoStateChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .contentvisibilityautostatechange); + return self.getAttributeFunction(.oncontentvisibilityautostatechange, page); } pub fn setOnContextLost(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .contextlost, callback); + return page.setAttrListener(self.asElement(), .oncontextlost, callback); } pub fn getOnContextLost(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .contextlost); + return self.getAttributeFunction(.oncontextlost, page); } pub fn setOnContextMenu(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .contextmenu, callback); + return page.setAttrListener(self.asElement(), .oncontextmenu, callback); } pub fn getOnContextMenu(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .contextmenu); + return self.getAttributeFunction(.oncontextmenu, page); } pub fn setOnContextRestored(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .contextrestored, callback); + return page.setAttrListener(self.asElement(), .oncontextrestored, callback); } pub fn getOnContextRestored(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .contextrestored); + return self.getAttributeFunction(.oncontextrestored, page); } pub fn setOnCopy(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .copy, callback); + return page.setAttrListener(self.asElement(), .oncopy, callback); } pub fn getOnCopy(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .copy); + return self.getAttributeFunction(.oncopy, page); } pub fn setOnCueChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .cuechange, callback); + return page.setAttrListener(self.asElement(), .oncuechange, callback); } pub fn getOnCueChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .cuechange); + return self.getAttributeFunction(.oncuechange, page); } pub fn setOnCut(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .cut, callback); + return page.setAttrListener(self.asElement(), .oncut, callback); } pub fn getOnCut(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .cut); + return self.getAttributeFunction(.oncut, page); } pub fn setOnDblClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dblclick, callback); + return page.setAttrListener(self.asElement(), .ondblclick, callback); } pub fn getOnDblClick(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dblclick); + return self.getAttributeFunction(.ondblclick, page); } pub fn setOnDrag(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .drag, callback); + return page.setAttrListener(self.asElement(), .ondrag, callback); } pub fn getOnDrag(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .drag); + return self.getAttributeFunction(.ondrag, page); } pub fn setOnDragEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dragend, callback); + return page.setAttrListener(self.asElement(), .ondragend, callback); } pub fn getOnDragEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dragend); + return self.getAttributeFunction(.ondragend, page); } pub fn setOnDragEnter(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dragenter, callback); + return page.setAttrListener(self.asElement(), .ondragenter, callback); } pub fn getOnDragEnter(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dragenter); + return self.getAttributeFunction(.ondragenter, page); } pub fn setOnDragExit(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dragexit, callback); + return page.setAttrListener(self.asElement(), .ondragexit, callback); } pub fn getOnDragExit(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dragexit); + return self.getAttributeFunction(.ondragexit, page); } pub fn setOnDragLeave(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dragleave, callback); + return page.setAttrListener(self.asElement(), .ondragleave, callback); } pub fn getOnDragLeave(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dragleave); + return self.getAttributeFunction(.ondragleave, page); } pub fn setOnDragOver(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dragover, callback); + return page.setAttrListener(self.asElement(), .ondragover, callback); } pub fn getOnDragOver(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dragover); + return self.getAttributeFunction(.ondragover, page); } pub fn setOnDragStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .dragstart, callback); + return page.setAttrListener(self.asElement(), .ondragstart, callback); } pub fn getOnDragStart(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .dragstart); + return self.getAttributeFunction(.ondragstart, page); } pub fn setOnDrop(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .drop, callback); + return page.setAttrListener(self.asElement(), .ondrop, callback); } pub fn getOnDrop(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .drop); + return self.getAttributeFunction(.ondrop, page); } pub fn setOnDurationChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .durationchange, callback); + return page.setAttrListener(self.asElement(), .ondurationchange, callback); } pub fn getOnDurationChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .durationchange); + return self.getAttributeFunction(.ondurationchange, page); } pub fn setOnEmptied(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .emptied, callback); + return page.setAttrListener(self.asElement(), .onemptied, callback); } pub fn getOnEmptied(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .emptied); + return self.getAttributeFunction(.onemptied, page); } pub fn setOnEnded(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .ended, callback); + return page.setAttrListener(self.asElement(), .onended, callback); } pub fn getOnEnded(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .ended); + return self.getAttributeFunction(.onended, page); } pub fn setOnError(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .@"error", callback); + return page.setAttrListener(self.asElement(), .onerror, callback); } pub fn getOnError(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .@"error"); + return self.getAttributeFunction(.onerror, page); } pub fn setOnFocus(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .focus, callback); + return page.setAttrListener(self.asElement(), .onfocus, callback); } pub fn getOnFocus(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .focus); + return self.getAttributeFunction(.onfocus, page); } pub fn setOnFormData(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .formdata, callback); + return page.setAttrListener(self.asElement(), .onformdata, callback); } pub fn getOnFormData(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .formdata); + return self.getAttributeFunction(.onformdata, page); } pub fn setOnFullscreenChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .fullscreenchange, callback); + return page.setAttrListener(self.asElement(), .onfullscreenchange, callback); } pub fn getOnFullscreenChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .fullscreenchange); + return self.getAttributeFunction(.onfullscreenchange, page); } pub fn setOnFullscreenError(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .fullscreenerror, callback); + return page.setAttrListener(self.asElement(), .onfullscreenerror, callback); } pub fn getOnFullscreenError(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .fullscreenerror); + return self.getAttributeFunction(.onfullscreenerror, page); } pub fn setOnGotPointerCapture(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .gotpointercapture, callback); + return page.setAttrListener(self.asElement(), .ongotpointercapture, callback); } pub fn getOnGotPointerCapture(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .gotpointercapture); + return self.getAttributeFunction(.ongotpointercapture, page); } pub fn setOnInput(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .input, callback); + return page.setAttrListener(self.asElement(), .oninput, callback); } pub fn getOnInput(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .input); + return self.getAttributeFunction(.oninput, page); } pub fn setOnInvalid(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .invalid, callback); + return page.setAttrListener(self.asElement(), .oninvalid, callback); } pub fn getOnInvalid(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .invalid); + return self.getAttributeFunction(.oninvalid, page); } pub fn setOnKeyDown(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .keydown, callback); + return page.setAttrListener(self.asElement(), .onkeydown, callback); } pub fn getOnKeyDown(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .keydown); + return self.getAttributeFunction(.onkeydown, page); } pub fn setOnKeyPress(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .keypress, callback); + return page.setAttrListener(self.asElement(), .onkeypress, callback); } pub fn getOnKeyPress(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .keypress); + return self.getAttributeFunction(.onkeypress, page); } pub fn setOnKeyUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .keyup, callback); + return page.setAttrListener(self.asElement(), .onkeyup, callback); } pub fn getOnKeyUp(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .keyup); + return self.getAttributeFunction(.onkeyup, page); } pub fn setOnLoad(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .load, callback); + return page.setAttrListener(self.asElement(), .onload, callback); } pub fn getOnLoad(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .load); + return self.getAttributeFunction(.onload, page); } pub fn setOnLoadedData(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .loadeddata, callback); + return page.setAttrListener(self.asElement(), .onloadeddata, callback); } pub fn getOnLoadedData(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .loadeddata); + return self.getAttributeFunction(.onloadeddata, page); } pub fn setOnLoadedMetadata(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .loadedmetadata, callback); + return page.setAttrListener(self.asElement(), .onloadedmetadata, callback); } pub fn getOnLoadedMetadata(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .loadedmetadata); + return self.getAttributeFunction(.onloadedmetadata, page); } pub fn setOnLoadStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .loadstart, callback); + return page.setAttrListener(self.asElement(), .onloadstart, callback); } pub fn getOnLoadStart(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .loadstart); + return self.getAttributeFunction(.onloadstart, page); } pub fn setOnLostPointerCapture(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .lostpointercapture, callback); + return page.setAttrListener(self.asElement(), .onlostpointercapture, callback); } pub fn getOnLostPointerCapture(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .lostpointercapture); + return self.getAttributeFunction(.onlostpointercapture, page); } pub fn setOnMouseDown(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .mousedown, callback); + return page.setAttrListener(self.asElement(), .onmousedown, callback); } pub fn getOnMouseDown(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .mousedown); + return self.getAttributeFunction(.onmousedown, page); } pub fn setOnMouseMove(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .mousemove, callback); + return page.setAttrListener(self.asElement(), .onmousemove, callback); } pub fn getOnMouseMove(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .mousemove); + return self.getAttributeFunction(.onmousemove, page); } pub fn setOnMouseOut(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .mouseout, callback); + return page.setAttrListener(self.asElement(), .onmouseout, callback); } pub fn getOnMouseOut(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .mouseout); + return self.getAttributeFunction(.onmouseout, page); } pub fn setOnMouseOver(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .mouseover, callback); + return page.setAttrListener(self.asElement(), .onmouseover, callback); } pub fn getOnMouseOver(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .mouseover); + return self.getAttributeFunction(.onmouseover, page); } pub fn setOnMouseUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .mouseup, callback); + return page.setAttrListener(self.asElement(), .onmouseup, callback); } pub fn getOnMouseUp(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .mouseup); + return self.getAttributeFunction(.onmouseup, page); } pub fn setOnPaste(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .paste, callback); + return page.setAttrListener(self.asElement(), .onpaste, callback); } pub fn getOnPaste(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .paste); + return self.getAttributeFunction(.onpaste, page); } pub fn setOnPause(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pause, callback); + return page.setAttrListener(self.asElement(), .onpause, callback); } pub fn getOnPause(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pause); + return self.getAttributeFunction(.onpause, page); } pub fn setOnPlay(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .play, callback); + return page.setAttrListener(self.asElement(), .onplay, callback); } pub fn getOnPlay(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .play); + return self.getAttributeFunction(.onplay, page); } pub fn setOnPlaying(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .playing, callback); + return page.setAttrListener(self.asElement(), .onplaying, callback); } pub fn getOnPlaying(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .playing); + return self.getAttributeFunction(.onplaying, page); } pub fn setOnPointerCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointercancel, callback); + return page.setAttrListener(self.asElement(), .onpointercancel, callback); } pub fn getOnPointerCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointercancel); + return self.getAttributeFunction(.onpointercancel, page); } pub fn setOnPointerDown(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerdown, callback); + return page.setAttrListener(self.asElement(), .onpointerdown, callback); } pub fn getOnPointerDown(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerdown); + return self.getAttributeFunction(.onpointerdown, page); } pub fn setOnPointerEnter(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerenter, callback); + return page.setAttrListener(self.asElement(), .onpointerenter, callback); } pub fn getOnPointerEnter(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerenter); + return self.getAttributeFunction(.onpointerenter, page); } pub fn setOnPointerLeave(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerleave, callback); + return page.setAttrListener(self.asElement(), .onpointerleave, callback); } pub fn getOnPointerLeave(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerleave); + return self.getAttributeFunction(.onpointerleave, page); } pub fn setOnPointerMove(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointermove, callback); + return page.setAttrListener(self.asElement(), .onpointermove, callback); } pub fn getOnPointerMove(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointermove); + return self.getAttributeFunction(.onpointermove, page); } pub fn setOnPointerOut(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerout, callback); + return page.setAttrListener(self.asElement(), .onpointerout, callback); } pub fn getOnPointerOut(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerout); + return self.getAttributeFunction(.onpointerout, page); } pub fn setOnPointerOver(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerover, callback); + return page.setAttrListener(self.asElement(), .onpointerover, callback); } pub fn getOnPointerOver(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerover); + return self.getAttributeFunction(.onpointerover, page); } pub fn setOnPointerRawUpdate(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerrawupdate, callback); + return page.setAttrListener(self.asElement(), .onpointerrawupdate, callback); } pub fn getOnPointerRawUpdate(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerrawupdate); + return self.getAttributeFunction(.onpointerrawupdate, page); } pub fn setOnPointerUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .pointerup, callback); + return page.setAttrListener(self.asElement(), .onpointerup, callback); } pub fn getOnPointerUp(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .pointerup); + return self.getAttributeFunction(.onpointerup, page); } pub fn setOnProgress(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .progress, callback); + return page.setAttrListener(self.asElement(), .onprogress, callback); } pub fn getOnProgress(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .progress); + return self.getAttributeFunction(.onprogress, page); } pub fn setOnRateChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .ratechange, callback); + return page.setAttrListener(self.asElement(), .onratechange, callback); } pub fn getOnRateChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .ratechange); + return self.getAttributeFunction(.onratechange, page); } pub fn setOnReset(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .reset, callback); + return page.setAttrListener(self.asElement(), .onreset, callback); } pub fn getOnReset(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .reset); + return self.getAttributeFunction(.onreset, page); } pub fn setOnResize(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .resize, callback); + return page.setAttrListener(self.asElement(), .onresize, callback); } pub fn getOnResize(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .resize); + return self.getAttributeFunction(.onresize, page); } pub fn setOnScroll(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .scroll, callback); + return page.setAttrListener(self.asElement(), .onscroll, callback); } pub fn getOnScroll(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .scroll); + return self.getAttributeFunction(.onscroll, page); } pub fn setOnScrollEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .scrollend, callback); + return page.setAttrListener(self.asElement(), .onscrollend, callback); } pub fn getOnScrollEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .scrollend); + return self.getAttributeFunction(.onscrollend, page); } pub fn setOnSecurityPolicyViolation(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .securitypolicyviolation, callback); + return page.setAttrListener(self.asElement(), .onsecuritypolicyviolation, callback); } pub fn getOnSecurityPolicyViolation(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .securitypolicyviolation); + return self.getAttributeFunction(.onsecuritypolicyviolation, page); } pub fn setOnSeeked(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .seeked, callback); + return page.setAttrListener(self.asElement(), .onseeked, callback); } pub fn getOnSeeked(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .seeked); + return self.getAttributeFunction(.onseeked, page); } pub fn setOnSeeking(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .seeking, callback); + return page.setAttrListener(self.asElement(), .onseeking, callback); } pub fn getOnSeeking(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .seeking); + return self.getAttributeFunction(.onseeking, page); } pub fn setOnSelect(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .select, callback); + return page.setAttrListener(self.asElement(), .onselect, callback); } pub fn getOnSelect(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .select); + return self.getAttributeFunction(.onselect, page); } pub fn setOnSelectionChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .selectionchange, callback); + return page.setAttrListener(self.asElement(), .onselectionchange, callback); } pub fn getOnSelectionChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .selectionchange); + return self.getAttributeFunction(.onselectionchange, page); } pub fn setOnSelectStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .selectstart, callback); + return page.setAttrListener(self.asElement(), .onselectstart, callback); } pub fn getOnSelectStart(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .selectstart); + return self.getAttributeFunction(.onselectstart, page); } pub fn setOnSlotChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .slotchange, callback); + return page.setAttrListener(self.asElement(), .onslotchange, callback); } pub fn getOnSlotChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .slotchange); + return self.getAttributeFunction(.onslotchange, page); } pub fn setOnStalled(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .stalled, callback); + return page.setAttrListener(self.asElement(), .onstalled, callback); } pub fn getOnStalled(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .stalled); + return self.getAttributeFunction(.onstalled, page); } pub fn setOnSubmit(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .submit, callback); + return page.setAttrListener(self.asElement(), .onsubmit, callback); } pub fn getOnSubmit(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .submit); + return self.getAttributeFunction(.onsubmit, page); } pub fn setOnSuspend(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .@"suspend", callback); + return page.setAttrListener(self.asElement(), .onsuspend, callback); } pub fn getOnSuspend(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .@"suspend"); + return self.getAttributeFunction(.onsuspend, page); } pub fn setOnTimeUpdate(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .timeupdate, callback); + return page.setAttrListener(self.asElement(), .ontimeupdate, callback); } pub fn getOnTimeUpdate(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .timeupdate); + return self.getAttributeFunction(.ontimeupdate, page); } pub fn setOnToggle(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .toggle, callback); + return page.setAttrListener(self.asElement(), .ontoggle, callback); } pub fn getOnToggle(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .toggle); + return self.getAttributeFunction(.ontoggle, page); } pub fn setOnTransitionCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .transitioncancel, callback); + return page.setAttrListener(self.asElement(), .ontransitioncancel, callback); } pub fn getOnTransitionCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .transitioncancel); + return self.getAttributeFunction(.ontransitioncancel, page); } pub fn setOnTransitionEnd(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .transitionend, callback); + return page.setAttrListener(self.asElement(), .ontransitionend, callback); } pub fn getOnTransitionEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .transitionend); + return self.getAttributeFunction(.ontransitionend, page); } pub fn setOnTransitionRun(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .transitionrun, callback); + return page.setAttrListener(self.asElement(), .ontransitionrun, callback); } pub fn getOnTransitionRun(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .transitionrun); + return self.getAttributeFunction(.ontransitionrun, page); } pub fn setOnTransitionStart(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .transitionstart, callback); + return page.setAttrListener(self.asElement(), .ontransitionstart, callback); } pub fn getOnTransitionStart(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .transitionstart); + return self.getAttributeFunction(.ontransitionstart, page); } pub fn setOnVolumeChange(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .volumechange, callback); + return page.setAttrListener(self.asElement(), .onvolumechange, callback); } pub fn getOnVolumeChange(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .volumechange); + return self.getAttributeFunction(.onvolumechange, page); } pub fn setOnWaiting(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .waiting, callback); + return page.setAttrListener(self.asElement(), .onwaiting, callback); } pub fn getOnWaiting(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .waiting); + return self.getAttributeFunction(.onwaiting, page); } pub fn setOnWheel(self: *HtmlElement, callback: js.Function.Global, page: *Page) !void { - return page.setAttrListener(self.asElement(), .wheel, callback); + return page.setAttrListener(self.asElement(), .onwheel, callback); } pub fn getOnWheel(self: *HtmlElement, page: *Page) ?js.Function.Global { - return page.getAttrListener(self.asElement(), .wheel); + return self.getAttributeFunction(.onwheel, page); } pub const JsApi = struct { From 13dbdc7dc7606bce58227754498c5ba6360ec934 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 11:46:35 +0300 Subject: [PATCH 06/10] import order --- src/browser/webapi/element/Html.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 0a887ac7..54e200e8 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -18,8 +18,8 @@ const std = @import("std"); const js = @import("../../js/js.zig"); -const log = @import("../../../log.zig"); const reflect = @import("../../reflect.zig"); +const log = @import("../../../log.zig"); const Page = @import("../../Page.zig"); const Node = @import("../Node.zig"); From 3c660f2cb0e608df0b6fddbb1ca00f6c6267bf70 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 11:46:53 +0300 Subject: [PATCH 07/10] remove unnecessary `comptime` --- src/browser/webapi/element/Html.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 54e200e8..4a6f107b 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -335,7 +335,7 @@ pub fn click(self: *HtmlElement, page: *Page) !void { fn getAttributeFunction( self: *HtmlElement, - comptime listener_type: Element.KnownListener, + listener_type: Element.KnownListener, page: *Page, ) ?js.Function.Global { const element = self.asElement(); From 39c90247470dd7555b28314096b2415b8d51671e Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 11:49:04 +0300 Subject: [PATCH 08/10] `!?js.Function.Global` Also more clear warning in `stringToPersistedFunction` failure. --- src/browser/webapi/element/Html.zig | 219 ++++++++++++++-------------- 1 file changed, 107 insertions(+), 112 deletions(-) diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 4a6f107b..4f5669c7 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -337,32 +337,27 @@ fn getAttributeFunction( self: *HtmlElement, listener_type: Element.KnownListener, page: *Page, -) ?js.Function.Global { +) !?js.Function.Global { const element = self.asElement(); if (page.getAttrListener(element, listener_type)) |cached| { return cached; } const attr = element.getAttributeSafe(.wrap(@tagName(listener_type))) orelse return null; - const callback = page.js.stringToPersistedFunction(attr) catch |err| { - // Not a valid expression; log this to find out if its something we should be supporting. - log.warn(.unknown_prop, "Page.getAttrListener", .{ - .expression = attr, - .err = err, - }); + const callback = page.js.stringToPersistedFunction(attr) catch |err| switch (err) { + error.OutOfMemory => return err, + else => { + // Not a valid expression; log this to find out if its something we should be supporting. + log.warn(.js, "Html.getAttributeFunction", .{ + .expression = attr, + .err = err, + }); - return null; + return null; + }, }; - page.setAttrListener(element, listener_type, callback) catch { - // This is fine :tm: We're out of memory for cache. - // I don't want to make all getters "!?" just because of this honestly. - log.warn(.app, "getAttributeFunction", .{ - .element = element, - .listener_type = listener_type, - .callback = callback, - }); - }; + try page.setAttrListener(element, listener_type, callback); return callback; } @@ -371,7 +366,7 @@ pub fn setOnAbort(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onabort, callback); } -pub fn getOnAbort(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnAbort(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onabort, page); } @@ -379,7 +374,7 @@ pub fn setOnAnimationCancel(self: *HtmlElement, callback: js.Function.Global, pa return page.setAttrListener(self.asElement(), .onanimationcancel, callback); } -pub fn getOnAnimationCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnAnimationCancel(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onanimationcancel, page); } @@ -387,7 +382,7 @@ pub fn setOnAnimationEnd(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onanimationend, callback); } -pub fn getOnAnimationEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnAnimationEnd(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onanimationend, page); } @@ -395,7 +390,7 @@ pub fn setOnAnimationIteration(self: *HtmlElement, callback: js.Function.Global, return page.setAttrListener(self.asElement(), .onanimationiteration, callback); } -pub fn getOnAnimationIteration(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnAnimationIteration(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onanimationiteration, page); } @@ -403,7 +398,7 @@ pub fn setOnAnimationStart(self: *HtmlElement, callback: js.Function.Global, pag return page.setAttrListener(self.asElement(), .onanimationstart, callback); } -pub fn getOnAnimationStart(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnAnimationStart(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onanimationstart, page); } @@ -411,7 +406,7 @@ pub fn setOnAuxClick(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .onauxclick, callback); } -pub fn getOnAuxClick(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnAuxClick(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onauxclick, page); } @@ -419,7 +414,7 @@ pub fn setOnBeforeInput(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onbeforeinput, callback); } -pub fn getOnBeforeInput(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnBeforeInput(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onbeforeinput, page); } @@ -427,7 +422,7 @@ pub fn setOnBeforeMatch(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onbeforematch, callback); } -pub fn getOnBeforeMatch(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnBeforeMatch(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onbeforematch, page); } @@ -435,7 +430,7 @@ pub fn setOnBeforeToggle(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onbeforetoggle, callback); } -pub fn getOnBeforeToggle(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnBeforeToggle(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onbeforetoggle, page); } @@ -443,7 +438,7 @@ pub fn setOnBlur(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onblur, callback); } -pub fn getOnBlur(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnBlur(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onblur, page); } @@ -451,7 +446,7 @@ pub fn setOnCancel(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .oncancel, callback); } -pub fn getOnCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCancel(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncancel, page); } @@ -459,7 +454,7 @@ pub fn setOnCanPlay(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .oncanplay, callback); } -pub fn getOnCanPlay(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCanPlay(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncanplay, page); } @@ -467,7 +462,7 @@ pub fn setOnCanPlayThrough(self: *HtmlElement, callback: js.Function.Global, pag return page.setAttrListener(self.asElement(), .oncanplaythrough, callback); } -pub fn getOnCanPlayThrough(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCanPlayThrough(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncanplaythrough, page); } @@ -475,7 +470,7 @@ pub fn setOnChange(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .onchange, callback); } -pub fn getOnChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onchange, page); } @@ -483,7 +478,7 @@ pub fn setOnClick(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onclick, callback); } -pub fn getOnClick(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnClick(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onclick, page); } @@ -491,7 +486,7 @@ pub fn setOnClose(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onclose, callback); } -pub fn getOnClose(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnClose(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onclose, page); } @@ -499,7 +494,7 @@ pub fn setOnCommand(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .oncommand, callback); } -pub fn getOnCommand(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCommand(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncommand, page); } @@ -507,7 +502,7 @@ pub fn setOnContentVisibilityAutoStateChange(self: *HtmlElement, callback: js.Fu return page.setAttrListener(self.asElement(), .oncontentvisibilityautostatechange, callback); } -pub fn getOnContentVisibilityAutoStateChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnContentVisibilityAutoStateChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncontentvisibilityautostatechange, page); } @@ -515,7 +510,7 @@ pub fn setOnContextLost(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .oncontextlost, callback); } -pub fn getOnContextLost(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnContextLost(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncontextlost, page); } @@ -523,7 +518,7 @@ pub fn setOnContextMenu(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .oncontextmenu, callback); } -pub fn getOnContextMenu(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnContextMenu(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncontextmenu, page); } @@ -531,7 +526,7 @@ pub fn setOnContextRestored(self: *HtmlElement, callback: js.Function.Global, pa return page.setAttrListener(self.asElement(), .oncontextrestored, callback); } -pub fn getOnContextRestored(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnContextRestored(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncontextrestored, page); } @@ -539,7 +534,7 @@ pub fn setOnCopy(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .oncopy, callback); } -pub fn getOnCopy(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCopy(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncopy, page); } @@ -547,7 +542,7 @@ pub fn setOnCueChange(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .oncuechange, callback); } -pub fn getOnCueChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCueChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncuechange, page); } @@ -555,7 +550,7 @@ pub fn setOnCut(self: *HtmlElement, callback: js.Function.Global, page: *Page) ! return page.setAttrListener(self.asElement(), .oncut, callback); } -pub fn getOnCut(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnCut(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oncut, page); } @@ -563,7 +558,7 @@ pub fn setOnDblClick(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .ondblclick, callback); } -pub fn getOnDblClick(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDblClick(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondblclick, page); } @@ -571,7 +566,7 @@ pub fn setOnDrag(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .ondrag, callback); } -pub fn getOnDrag(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDrag(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondrag, page); } @@ -579,7 +574,7 @@ pub fn setOnDragEnd(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .ondragend, callback); } -pub fn getOnDragEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDragEnd(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondragend, page); } @@ -587,7 +582,7 @@ pub fn setOnDragEnter(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .ondragenter, callback); } -pub fn getOnDragEnter(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDragEnter(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondragenter, page); } @@ -595,7 +590,7 @@ pub fn setOnDragExit(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .ondragexit, callback); } -pub fn getOnDragExit(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDragExit(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondragexit, page); } @@ -603,7 +598,7 @@ pub fn setOnDragLeave(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .ondragleave, callback); } -pub fn getOnDragLeave(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDragLeave(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondragleave, page); } @@ -611,7 +606,7 @@ pub fn setOnDragOver(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .ondragover, callback); } -pub fn getOnDragOver(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDragOver(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondragover, page); } @@ -619,7 +614,7 @@ pub fn setOnDragStart(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .ondragstart, callback); } -pub fn getOnDragStart(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDragStart(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondragstart, page); } @@ -627,7 +622,7 @@ pub fn setOnDrop(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .ondrop, callback); } -pub fn getOnDrop(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDrop(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondrop, page); } @@ -635,7 +630,7 @@ pub fn setOnDurationChange(self: *HtmlElement, callback: js.Function.Global, pag return page.setAttrListener(self.asElement(), .ondurationchange, callback); } -pub fn getOnDurationChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnDurationChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ondurationchange, page); } @@ -643,7 +638,7 @@ pub fn setOnEmptied(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onemptied, callback); } -pub fn getOnEmptied(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnEmptied(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onemptied, page); } @@ -651,7 +646,7 @@ pub fn setOnEnded(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onended, callback); } -pub fn getOnEnded(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnEnded(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onended, page); } @@ -659,7 +654,7 @@ pub fn setOnError(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onerror, callback); } -pub fn getOnError(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnError(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onerror, page); } @@ -667,7 +662,7 @@ pub fn setOnFocus(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onfocus, callback); } -pub fn getOnFocus(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnFocus(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onfocus, page); } @@ -675,7 +670,7 @@ pub fn setOnFormData(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .onformdata, callback); } -pub fn getOnFormData(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnFormData(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onformdata, page); } @@ -683,7 +678,7 @@ pub fn setOnFullscreenChange(self: *HtmlElement, callback: js.Function.Global, p return page.setAttrListener(self.asElement(), .onfullscreenchange, callback); } -pub fn getOnFullscreenChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnFullscreenChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onfullscreenchange, page); } @@ -691,7 +686,7 @@ pub fn setOnFullscreenError(self: *HtmlElement, callback: js.Function.Global, pa return page.setAttrListener(self.asElement(), .onfullscreenerror, callback); } -pub fn getOnFullscreenError(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnFullscreenError(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onfullscreenerror, page); } @@ -699,7 +694,7 @@ pub fn setOnGotPointerCapture(self: *HtmlElement, callback: js.Function.Global, return page.setAttrListener(self.asElement(), .ongotpointercapture, callback); } -pub fn getOnGotPointerCapture(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnGotPointerCapture(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ongotpointercapture, page); } @@ -707,7 +702,7 @@ pub fn setOnInput(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .oninput, callback); } -pub fn getOnInput(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnInput(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oninput, page); } @@ -715,7 +710,7 @@ pub fn setOnInvalid(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .oninvalid, callback); } -pub fn getOnInvalid(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnInvalid(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.oninvalid, page); } @@ -723,7 +718,7 @@ pub fn setOnKeyDown(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onkeydown, callback); } -pub fn getOnKeyDown(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnKeyDown(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onkeydown, page); } @@ -731,7 +726,7 @@ pub fn setOnKeyPress(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .onkeypress, callback); } -pub fn getOnKeyPress(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnKeyPress(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onkeypress, page); } @@ -739,7 +734,7 @@ pub fn setOnKeyUp(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onkeyup, callback); } -pub fn getOnKeyUp(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnKeyUp(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onkeyup, page); } @@ -747,7 +742,7 @@ pub fn setOnLoad(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onload, callback); } -pub fn getOnLoad(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnLoad(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onload, page); } @@ -755,7 +750,7 @@ pub fn setOnLoadedData(self: *HtmlElement, callback: js.Function.Global, page: * return page.setAttrListener(self.asElement(), .onloadeddata, callback); } -pub fn getOnLoadedData(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnLoadedData(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onloadeddata, page); } @@ -763,7 +758,7 @@ pub fn setOnLoadedMetadata(self: *HtmlElement, callback: js.Function.Global, pag return page.setAttrListener(self.asElement(), .onloadedmetadata, callback); } -pub fn getOnLoadedMetadata(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnLoadedMetadata(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onloadedmetadata, page); } @@ -771,7 +766,7 @@ pub fn setOnLoadStart(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .onloadstart, callback); } -pub fn getOnLoadStart(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnLoadStart(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onloadstart, page); } @@ -779,7 +774,7 @@ pub fn setOnLostPointerCapture(self: *HtmlElement, callback: js.Function.Global, return page.setAttrListener(self.asElement(), .onlostpointercapture, callback); } -pub fn getOnLostPointerCapture(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnLostPointerCapture(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onlostpointercapture, page); } @@ -787,7 +782,7 @@ pub fn setOnMouseDown(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .onmousedown, callback); } -pub fn getOnMouseDown(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnMouseDown(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onmousedown, page); } @@ -795,7 +790,7 @@ pub fn setOnMouseMove(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .onmousemove, callback); } -pub fn getOnMouseMove(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnMouseMove(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onmousemove, page); } @@ -803,7 +798,7 @@ pub fn setOnMouseOut(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .onmouseout, callback); } -pub fn getOnMouseOut(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnMouseOut(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onmouseout, page); } @@ -811,7 +806,7 @@ pub fn setOnMouseOver(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .onmouseover, callback); } -pub fn getOnMouseOver(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnMouseOver(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onmouseover, page); } @@ -819,7 +814,7 @@ pub fn setOnMouseUp(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onmouseup, callback); } -pub fn getOnMouseUp(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnMouseUp(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onmouseup, page); } @@ -827,7 +822,7 @@ pub fn setOnPaste(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onpaste, callback); } -pub fn getOnPaste(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPaste(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpaste, page); } @@ -835,7 +830,7 @@ pub fn setOnPause(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onpause, callback); } -pub fn getOnPause(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPause(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpause, page); } @@ -843,7 +838,7 @@ pub fn setOnPlay(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onplay, callback); } -pub fn getOnPlay(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPlay(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onplay, page); } @@ -851,7 +846,7 @@ pub fn setOnPlaying(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onplaying, callback); } -pub fn getOnPlaying(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPlaying(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onplaying, page); } @@ -859,7 +854,7 @@ pub fn setOnPointerCancel(self: *HtmlElement, callback: js.Function.Global, page return page.setAttrListener(self.asElement(), .onpointercancel, callback); } -pub fn getOnPointerCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerCancel(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointercancel, page); } @@ -867,7 +862,7 @@ pub fn setOnPointerDown(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onpointerdown, callback); } -pub fn getOnPointerDown(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerDown(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerdown, page); } @@ -875,7 +870,7 @@ pub fn setOnPointerEnter(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onpointerenter, callback); } -pub fn getOnPointerEnter(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerEnter(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerenter, page); } @@ -883,7 +878,7 @@ pub fn setOnPointerLeave(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onpointerleave, callback); } -pub fn getOnPointerLeave(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerLeave(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerleave, page); } @@ -891,7 +886,7 @@ pub fn setOnPointerMove(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onpointermove, callback); } -pub fn getOnPointerMove(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerMove(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointermove, page); } @@ -899,7 +894,7 @@ pub fn setOnPointerOut(self: *HtmlElement, callback: js.Function.Global, page: * return page.setAttrListener(self.asElement(), .onpointerout, callback); } -pub fn getOnPointerOut(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerOut(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerout, page); } @@ -907,7 +902,7 @@ pub fn setOnPointerOver(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onpointerover, callback); } -pub fn getOnPointerOver(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerOver(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerover, page); } @@ -915,7 +910,7 @@ pub fn setOnPointerRawUpdate(self: *HtmlElement, callback: js.Function.Global, p return page.setAttrListener(self.asElement(), .onpointerrawupdate, callback); } -pub fn getOnPointerRawUpdate(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerRawUpdate(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerrawupdate, page); } @@ -923,7 +918,7 @@ pub fn setOnPointerUp(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .onpointerup, callback); } -pub fn getOnPointerUp(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnPointerUp(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onpointerup, page); } @@ -931,7 +926,7 @@ pub fn setOnProgress(self: *HtmlElement, callback: js.Function.Global, page: *Pa return page.setAttrListener(self.asElement(), .onprogress, callback); } -pub fn getOnProgress(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnProgress(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onprogress, page); } @@ -939,7 +934,7 @@ pub fn setOnRateChange(self: *HtmlElement, callback: js.Function.Global, page: * return page.setAttrListener(self.asElement(), .onratechange, callback); } -pub fn getOnRateChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnRateChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onratechange, page); } @@ -947,7 +942,7 @@ pub fn setOnReset(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onreset, callback); } -pub fn getOnReset(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnReset(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onreset, page); } @@ -955,7 +950,7 @@ pub fn setOnResize(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .onresize, callback); } -pub fn getOnResize(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnResize(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onresize, page); } @@ -963,7 +958,7 @@ pub fn setOnScroll(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .onscroll, callback); } -pub fn getOnScroll(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnScroll(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onscroll, page); } @@ -971,7 +966,7 @@ pub fn setOnScrollEnd(self: *HtmlElement, callback: js.Function.Global, page: *P return page.setAttrListener(self.asElement(), .onscrollend, callback); } -pub fn getOnScrollEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnScrollEnd(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onscrollend, page); } @@ -979,7 +974,7 @@ pub fn setOnSecurityPolicyViolation(self: *HtmlElement, callback: js.Function.Gl return page.setAttrListener(self.asElement(), .onsecuritypolicyviolation, callback); } -pub fn getOnSecurityPolicyViolation(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSecurityPolicyViolation(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onsecuritypolicyviolation, page); } @@ -987,7 +982,7 @@ pub fn setOnSeeked(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .onseeked, callback); } -pub fn getOnSeeked(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSeeked(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onseeked, page); } @@ -995,7 +990,7 @@ pub fn setOnSeeking(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onseeking, callback); } -pub fn getOnSeeking(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSeeking(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onseeking, page); } @@ -1003,7 +998,7 @@ pub fn setOnSelect(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .onselect, callback); } -pub fn getOnSelect(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSelect(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onselect, page); } @@ -1011,7 +1006,7 @@ pub fn setOnSelectionChange(self: *HtmlElement, callback: js.Function.Global, pa return page.setAttrListener(self.asElement(), .onselectionchange, callback); } -pub fn getOnSelectionChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSelectionChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onselectionchange, page); } @@ -1019,7 +1014,7 @@ pub fn setOnSelectStart(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onselectstart, callback); } -pub fn getOnSelectStart(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSelectStart(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onselectstart, page); } @@ -1027,7 +1022,7 @@ pub fn setOnSlotChange(self: *HtmlElement, callback: js.Function.Global, page: * return page.setAttrListener(self.asElement(), .onslotchange, callback); } -pub fn getOnSlotChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSlotChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onslotchange, page); } @@ -1035,7 +1030,7 @@ pub fn setOnStalled(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onstalled, callback); } -pub fn getOnStalled(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnStalled(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onstalled, page); } @@ -1043,7 +1038,7 @@ pub fn setOnSubmit(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .onsubmit, callback); } -pub fn getOnSubmit(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSubmit(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onsubmit, page); } @@ -1051,7 +1046,7 @@ pub fn setOnSuspend(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onsuspend, callback); } -pub fn getOnSuspend(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnSuspend(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onsuspend, page); } @@ -1059,7 +1054,7 @@ pub fn setOnTimeUpdate(self: *HtmlElement, callback: js.Function.Global, page: * return page.setAttrListener(self.asElement(), .ontimeupdate, callback); } -pub fn getOnTimeUpdate(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnTimeUpdate(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ontimeupdate, page); } @@ -1067,7 +1062,7 @@ pub fn setOnToggle(self: *HtmlElement, callback: js.Function.Global, page: *Page return page.setAttrListener(self.asElement(), .ontoggle, callback); } -pub fn getOnToggle(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnToggle(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ontoggle, page); } @@ -1075,7 +1070,7 @@ pub fn setOnTransitionCancel(self: *HtmlElement, callback: js.Function.Global, p return page.setAttrListener(self.asElement(), .ontransitioncancel, callback); } -pub fn getOnTransitionCancel(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnTransitionCancel(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ontransitioncancel, page); } @@ -1083,7 +1078,7 @@ pub fn setOnTransitionEnd(self: *HtmlElement, callback: js.Function.Global, page return page.setAttrListener(self.asElement(), .ontransitionend, callback); } -pub fn getOnTransitionEnd(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnTransitionEnd(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ontransitionend, page); } @@ -1091,7 +1086,7 @@ pub fn setOnTransitionRun(self: *HtmlElement, callback: js.Function.Global, page return page.setAttrListener(self.asElement(), .ontransitionrun, callback); } -pub fn getOnTransitionRun(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnTransitionRun(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ontransitionrun, page); } @@ -1099,7 +1094,7 @@ pub fn setOnTransitionStart(self: *HtmlElement, callback: js.Function.Global, pa return page.setAttrListener(self.asElement(), .ontransitionstart, callback); } -pub fn getOnTransitionStart(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnTransitionStart(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.ontransitionstart, page); } @@ -1107,7 +1102,7 @@ pub fn setOnVolumeChange(self: *HtmlElement, callback: js.Function.Global, page: return page.setAttrListener(self.asElement(), .onvolumechange, callback); } -pub fn getOnVolumeChange(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnVolumeChange(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onvolumechange, page); } @@ -1115,7 +1110,7 @@ pub fn setOnWaiting(self: *HtmlElement, callback: js.Function.Global, page: *Pag return page.setAttrListener(self.asElement(), .onwaiting, callback); } -pub fn getOnWaiting(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnWaiting(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onwaiting, page); } @@ -1123,7 +1118,7 @@ pub fn setOnWheel(self: *HtmlElement, callback: js.Function.Global, page: *Page) return page.setAttrListener(self.asElement(), .onwheel, callback); } -pub fn getOnWheel(self: *HtmlElement, page: *Page) ?js.Function.Global { +pub fn getOnWheel(self: *HtmlElement, page: *Page) !?js.Function.Global { return self.getAttributeFunction(.onwheel, page); } From b19debff147d4539ac53a7daf9151966885692d8 Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 16:05:06 +0300 Subject: [PATCH 09/10] move everything to `global_event_handlers.zig` --- src/browser/Page.zig | 14 +- src/browser/webapi/Element.zig | 123 ---------------- src/browser/webapi/element/Html.zig | 6 +- src/browser/webapi/global_event_handlers.zig | 145 +++++++++++++++++++ 4 files changed, 159 insertions(+), 129 deletions(-) create mode 100644 src/browser/webapi/global_event_handlers.zig diff --git a/src/browser/Page.zig b/src/browser/Page.zig index abdb7845..657dad01 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -65,6 +65,9 @@ const timestamp = @import("../datetime.zig").timestamp; const milliTimestamp = @import("../datetime.zig").milliTimestamp; const WebApiURL = @import("webapi/URL.zig"); +const global_event_handlers = @import("webapi/global_event_handlers.zig"); +const GlobalEventHandlersLookup = global_event_handlers.Lookup; +const GlobalEventHandler = global_event_handlers.Handler; var default_url = WebApiURL{ ._raw = "about:blank" }; pub var default_location: Location = Location{ ._url = &default_url }; @@ -119,7 +122,7 @@ _element_assigned_slots: Element.AssignedSlotLookup = .{}, /// ```js /// img.setAttribute("onload", "(() => { ... })()"); /// ``` -_element_attr_listeners: Element.AttrListenerLookup = .{}, +_element_attr_listeners: GlobalEventHandlersLookup = .{}, _script_manager: ScriptManager, @@ -1215,7 +1218,7 @@ pub fn getElementByIdFromNode(self: *Page, node: *Node, id: []const u8) ?*Elemen pub fn setAttrListener( self: *Page, element: *Element, - listener_type: Element.KnownListener, + listener_type: GlobalEventHandler, listener_callback: JS.Function.Global, ) !void { if (comptime IS_DEBUG) { @@ -1225,7 +1228,7 @@ pub fn setAttrListener( }); } - const key = element.calcAttrListenerKey(listener_type); + const key = global_event_handlers.calculateKey(element.asEventTarget(), listener_type); const gop = try self._element_attr_listeners.getOrPut(self.arena, key); gop.value_ptr.* = listener_callback; } @@ -1234,9 +1237,10 @@ pub fn setAttrListener( pub fn getAttrListener( self: *const Page, element: *Element, - listener_type: Element.KnownListener, + listener_type: GlobalEventHandler, ) ?JS.Function.Global { - return self._element_attr_listeners.get(element.calcAttrListenerKey(listener_type)); + const key = global_event_handlers.calculateKey(element.asEventTarget(), listener_type); + return self._element_attr_listeners.get(key); } pub fn registerPerformanceObserver(self: *Page, observer: *PerformanceObserver) !void { diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 23da8d03..4a12f390 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -49,129 +49,6 @@ pub const RelListLookup = std.AutoHashMapUnmanaged(*Element, *collections.DOMTok pub const ShadowRootLookup = std.AutoHashMapUnmanaged(*Element, *ShadowRoot); pub const AssignedSlotLookup = std.AutoHashMapUnmanaged(*Element, *Html.Slot); -/// Better to discriminate it since not directly a pointer int. -/// -/// See `calcAttrListenerKey` to obtain one. -const AttrListenerKey = u64; -/// Use `getAttrListenerKey` to create a key. -pub const AttrListenerLookup = std.AutoHashMapUnmanaged(AttrListenerKey, js.Function.Global); - -/// Enum of known event listeners; increasing the size of it (u7) -/// can cause `AttrListenerKey` to behave incorrectly. -pub const KnownListener = enum(u7) { - onabort, - onanimationcancel, - onanimationend, - onanimationiteration, - onanimationstart, - onauxclick, - onbeforeinput, - onbeforematch, - onbeforetoggle, - onblur, - oncancel, - oncanplay, - oncanplaythrough, - onchange, - onclick, - onclose, - oncommand, - oncontentvisibilityautostatechange, - oncontextlost, - oncontextmenu, - oncontextrestored, - oncopy, - oncuechange, - oncut, - ondblclick, - ondrag, - ondragend, - ondragenter, - ondragexit, - ondragleave, - ondragover, - ondragstart, - ondrop, - ondurationchange, - onemptied, - onended, - onerror, - onfocus, - onformdata, - onfullscreenchange, - onfullscreenerror, - ongotpointercapture, - oninput, - oninvalid, - onkeydown, - onkeypress, - onkeyup, - onload, - onloadeddata, - onloadedmetadata, - onloadstart, - onlostpointercapture, - onmousedown, - onmousemove, - onmouseout, - onmouseover, - onmouseup, - onpaste, - onpause, - onplay, - onplaying, - onpointercancel, - onpointerdown, - onpointerenter, - onpointerleave, - onpointermove, - onpointerout, - onpointerover, - onpointerrawupdate, - onpointerup, - onprogress, - onratechange, - onreset, - onresize, - onscroll, - onscrollend, - onsecuritypolicyviolation, - onseeked, - onseeking, - onselect, - onselectionchange, - onselectstart, - onslotchange, - onstalled, - onsubmit, - onsuspend, - ontimeupdate, - ontoggle, - ontransitioncancel, - ontransitionend, - ontransitionrun, - ontransitionstart, - onvolumechange, - onwaiting, - onwheel, -}; - -/// Calculates a lookup key (`AttrListenerKey`) to use with `AttrListenerLookup` for an element. -/// NEVER use generated key to retrieve a pointer back. Portability is not guaranteed. -pub fn calcAttrListenerKey(self: *Element, event_type: KnownListener) AttrListenerKey { - // We can use `Element` for the key too; `EventTarget` is strict about - // its size and alignment, though. - const target = self.asEventTarget(); - // Check if we have 3 bits available from alignment of 8. - lp.assert(@alignOf(@TypeOf(target)) == 8, "calcAttrListenerKey: incorrect alignment", .{ - .event_target_alignment = @alignOf(@TypeOf(target)), - }); - - const ptr = @intFromPtr(target) >> 3; - lp.assert(ptr < (1 << 57), "calcAttrListenerKey: pointer overflow", .{ .ptr = ptr }); - return ptr | (@as(u64, @intFromEnum(event_type)) << 57); -} - pub const Namespace = enum(u8) { html, svg, diff --git a/src/browser/webapi/element/Html.zig b/src/browser/webapi/element/Html.zig index 4f5669c7..cc20622a 100644 --- a/src/browser/webapi/element/Html.zig +++ b/src/browser/webapi/element/Html.zig @@ -21,6 +21,10 @@ const js = @import("../../js/js.zig"); const reflect = @import("../../reflect.zig"); const log = @import("../../../log.zig"); +const global_event_handlers = @import("../global_event_handlers.zig"); +const GlobalEventHandlersLookup = global_event_handlers.Lookup; +const GlobalEventHandler = global_event_handlers.Handler; + const Page = @import("../../Page.zig"); const Node = @import("../Node.zig"); const Element = @import("../Element.zig"); @@ -335,7 +339,7 @@ pub fn click(self: *HtmlElement, page: *Page) !void { fn getAttributeFunction( self: *HtmlElement, - listener_type: Element.KnownListener, + listener_type: GlobalEventHandler, page: *Page, ) !?js.Function.Global { const element = self.asElement(); diff --git a/src/browser/webapi/global_event_handlers.zig b/src/browser/webapi/global_event_handlers.zig new file mode 100644 index 00000000..251fa8c6 --- /dev/null +++ b/src/browser/webapi/global_event_handlers.zig @@ -0,0 +1,145 @@ +// Copyright (C) 2023-2026 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); +const lp = @import("lightpanda"); + +const js = @import("../js/js.zig"); + +const EventTarget = @import("EventTarget.zig"); + +/// Better to discriminate it since not directly a pointer int. +/// +/// See `calculateKey` to obtain one. +const Key = u64; + +/// Use `calculateKey` to create a key. +pub const Lookup = std.AutoHashMapUnmanaged(Key, js.Function.Global); + +/// Enum of known event listeners; increasing the size of it (u7) +/// can cause `Key` to behave incorrectly. +pub const Handler = enum(u7) { + onabort, + onanimationcancel, + onanimationend, + onanimationiteration, + onanimationstart, + onauxclick, + onbeforeinput, + onbeforematch, + onbeforetoggle, + onblur, + oncancel, + oncanplay, + oncanplaythrough, + onchange, + onclick, + onclose, + oncommand, + oncontentvisibilityautostatechange, + oncontextlost, + oncontextmenu, + oncontextrestored, + oncopy, + oncuechange, + oncut, + ondblclick, + ondrag, + ondragend, + ondragenter, + ondragexit, + ondragleave, + ondragover, + ondragstart, + ondrop, + ondurationchange, + onemptied, + onended, + onerror, + onfocus, + onformdata, + onfullscreenchange, + onfullscreenerror, + ongotpointercapture, + oninput, + oninvalid, + onkeydown, + onkeypress, + onkeyup, + onload, + onloadeddata, + onloadedmetadata, + onloadstart, + onlostpointercapture, + onmousedown, + onmousemove, + onmouseout, + onmouseover, + onmouseup, + onpaste, + onpause, + onplay, + onplaying, + onpointercancel, + onpointerdown, + onpointerenter, + onpointerleave, + onpointermove, + onpointerout, + onpointerover, + onpointerrawupdate, + onpointerup, + onprogress, + onratechange, + onreset, + onresize, + onscroll, + onscrollend, + onsecuritypolicyviolation, + onseeked, + onseeking, + onselect, + onselectionchange, + onselectstart, + onslotchange, + onstalled, + onsubmit, + onsuspend, + ontimeupdate, + ontoggle, + ontransitioncancel, + ontransitionend, + ontransitionrun, + ontransitionstart, + onvolumechange, + onwaiting, + onwheel, +}; + +/// Calculates a lookup key to use with lookup for event target. +/// NEVER use generated key to retrieve a pointer back. Portability is not guaranteed. +pub fn calculateKey(event_target: *EventTarget, handler_type: Handler) Key { + // Check if we have 3 bits available from alignment of 8. + lp.assert(@alignOf(EventTarget) == 8, "calculateKey: incorrect alignment", .{ + .event_target_alignment = @alignOf(EventTarget), + }); + + const ptr = @intFromPtr(event_target) >> 3; + lp.assert(ptr < (1 << 57), "calculateKey: pointer overflow", .{ .ptr = ptr }); + return ptr | (@as(Key, @intFromEnum(handler_type)) << 57); +} From 95a000c279daf1c859759a4bc62215036a2361ee Mon Sep 17 00:00:00 2001 From: Halil Durak Date: Wed, 4 Feb 2026 16:15:02 +0300 Subject: [PATCH 10/10] `getOnSubmit` can return errors --- src/browser/Page.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 657dad01..8e86c47a 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -3144,7 +3144,7 @@ pub fn submitForm(self: *Page, submitter_: ?*Element, form_: ?*Element.Html.Form if (submit_opts.fire_event) { const submit_event = try Event.initTrusted("submit", .{ .bubbles = true, .cancelable = true }, self); - const onsubmit_handler = form.asHtmlElement().getOnSubmit(self); + const onsubmit_handler = try form.asHtmlElement().getOnSubmit(self); var ls: JS.Local.Scope = undefined; self.js.localScope(&ls);