diff --git a/src/browser/browser.zig b/src/browser/browser.zig index 00dbc9c2..550864b6 100644 --- a/src/browser/browser.zig +++ b/src/browser/browser.zig @@ -333,7 +333,7 @@ pub const Page = struct { // dispatch window.load event const loadevt = try parser.eventCreate(); try parser.eventInit(loadevt, "load", .{}); - _ = try parser.eventTargetDispatchEvent(parser.toEventTarget(Window, &self.session.window), loadevt); + _ = try parser.eventTargetDispatchEvent(parser.toEventTarget(EventTargetTBase, &self.session.window), loadevt); } // evalScript evaluates the src in priority. diff --git a/src/netsurf.zig b/src/netsurf.zig index 6e0afbfd..b0659b36 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -483,6 +483,11 @@ fn eventTargetVtable(et: *EventTarget) c.dom_event_target_vtable { } pub inline fn toEventTarget(comptime T: type, v: *T) *EventTarget { + if (comptime eventTargetTBaseFieldName(T)) |field| { + const et_aligned: *align(@alignOf(EventTarget)) EventTargetTBase = @alignCast(&@field(v, field)); + return @as(*EventTarget, @ptrCast(et_aligned)); + } + const et_aligned: *align(@alignOf(EventTarget)) T = @alignCast(v); return @as(*EventTarget, @ptrCast(et_aligned)); } @@ -633,6 +638,20 @@ pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool { return res; } +pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 { + std.debug.assert(@inComptime()); + switch (@typeInfo(T)) { + .Struct => |ti| { + for (ti.fields) |f| { + if (f.type == EventTargetTBase) return f.name; + } + }, + else => {}, + } + + return null; +} + // EventTargetBase is used to implement EventTarget for pure zig struct. pub const EventTargetTBase = struct { const Self = @This(); diff --git a/src/run_tests.zig b/src/run_tests.zig index ae5a247e..aac7fff7 100644 --- a/src/run_tests.zig +++ b/src/run_tests.zig @@ -143,6 +143,17 @@ test "Window is a libdom event target" { const event = try parser.eventCreate(); try parser.eventInit(event, "foo", .{}); - const et = @as(*parser.EventTarget, @ptrCast(&window)); + const et = parser.toEventTarget(Window, &window); + _ = try parser.eventTargetDispatchEvent(et, event); +} + +test "DocumentHTML is a libdom event target" { + doc = try parser.documentHTMLParseFromStr(""); + parser.documentHTMLClose(doc) catch {}; + + const event = try parser.eventCreate(); + try parser.eventInit(event, "foo", .{}); + + const et = parser.toEventTarget(parser.DocumentHTML, doc); _ = try parser.eventTargetDispatchEvent(et, event); }