From bc7055c98d43c25bb494ffee2312a581a9f86dfb Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Tue, 13 Feb 2024 15:16:03 +0100 Subject: [PATCH 1/3] netsurf: fix eventTargetVtable --- src/netsurf.zig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/netsurf.zig b/src/netsurf.zig index 035912d7..6e0afbfd 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -474,7 +474,12 @@ fn eventListenerGetData(lst: *EventListener) ?*anyopaque { pub const EventTarget = c.dom_event_target; fn eventTargetVtable(et: *EventTarget) c.dom_event_target_vtable { - return getVtable(c.dom_event_target_vtable, EventTarget, et); + // retrieve the vtable + const vtable = et.*.vtable.?; + // align correctly the vtable + const vtable_aligned: *align(@alignOf([*c]c.dom_event_target_vtable)) const anyopaque = @alignCast(vtable); + // convert the vtable to it's actual type and return it + return @as([*c]const c.dom_event_target_vtable, @ptrCast(vtable_aligned)).*; } pub inline fn toEventTarget(comptime T: type, v: *T) *EventTarget { From 069313817a2e34204cd613848c03b84fd3289ad2 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 15 Feb 2024 15:59:45 +0100 Subject: [PATCH 2/3] netsurf: use EventTargetTBase field to cast EventTarget --- src/browser/browser.zig | 2 +- src/netsurf.zig | 19 +++++++++++++++++++ src/run_tests.zig | 13 ++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) 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); } From 35ede4d79c58725279546fb5e58f3e6a7980f95f Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 15 Feb 2024 16:00:48 +0100 Subject: [PATCH 3/3] netsurf: declare EventTargetTBase as extern to guarantee the memory layout --- src/browser/browser.zig | 2 +- src/netsurf.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/browser.zig b/src/browser/browser.zig index 550864b6..00dbc9c2 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(EventTargetTBase, &self.session.window), loadevt); + _ = try parser.eventTargetDispatchEvent(parser.toEventTarget(Window, &self.session.window), loadevt); } // evalScript evaluates the src in priority. diff --git a/src/netsurf.zig b/src/netsurf.zig index b0659b36..b0d7c387 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -653,7 +653,7 @@ pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 { } // EventTargetBase is used to implement EventTarget for pure zig struct. -pub const EventTargetTBase = struct { +pub const EventTargetTBase = extern struct { const Self = @This(); vtable: ?*const c.struct_dom_event_target_vtable = &c.struct_dom_event_target_vtable{