EventTarget internal type for all

This commit is contained in:
sjorsdonkers
2025-07-11 09:49:29 +02:00
committed by Sjors
parent 2a2a9d7941
commit 5123697afe
8 changed files with 30 additions and 28 deletions

View File

@@ -16,6 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const std = @import("std");
const Env = @import("../env.zig").Env;
const parser = @import("../netsurf.zig");
const Page = @import("../page.zig").Page;
@@ -39,33 +40,30 @@ pub const EventTarget = struct {
// Extend libdom event target for pure zig struct.
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .plain },
pub fn toInterface(e: *parser.Event, et: *parser.EventTarget, page: *Page) !Union {
pub fn toInterface(et: *parser.EventTarget, page: *Page) !Union {
// libdom assumes that all event targets are libdom nodes. They are not.
// The window is a common non-node target, but it's easy to handle as
// its a singleton.
if (@intFromPtr(et) == @intFromPtr(&page.window.base)) {
return .{ .node = .{ .Window = &page.window } };
}
if (try parser.eventTargetInternalType(et) == .plain) {
return .{ .plain = et };
}
// AbortSignal is another non-node target. It has a distinct usage though
// so we hijack the event internal type to identity if.
switch (try parser.eventGetInternalType(e)) {
switch (try parser.eventTargetInternalType(et)) {
.libdom_node => {
return .{ .node = try nod.Node.toInterface(@as(*parser.Node, @ptrCast(et))) };
},
.plain => return .{ .plain = et },
.abort_signal => {
// AbortSignal is a special case, it has its own internal type.
// We return it as a node, but we need to handle it differently.
return .{ .node = .{ .AbortSignal = @fieldParentPtr("proto", @as(*parser.EventTargetTBase, @ptrCast(et))) } };
},
.xhr_event => {
.window => {
// The window is a common non-node target, but it's easy to handle as its a singleton.
std.debug.assert(@intFromPtr(et) == @intFromPtr(&page.window.base));
return .{ .node = .{ .Window = &page.window } };
},
.xhr => {
const XMLHttpRequestEventTarget = @import("../xhr/event_target.zig").XMLHttpRequestEventTarget;
const base: *XMLHttpRequestEventTarget = @fieldParentPtr("base", @as(*parser.EventTargetTBase, @ptrCast(et)));
return .{ .xhr = @fieldParentPtr("proto", base) };
},
else => {
return .{ .node = try nod.Node.toInterface(@as(*parser.Node, @ptrCast(et))) };
},
else => return error.MissingEventTargetType,
}
}

View File

@@ -39,7 +39,7 @@ pub const Performance = struct {
pub const prototype = *EventTarget;
// Extend libdom event target for pure zig struct.
base: parser.EventTargetTBase = parser.EventTargetTBase{},
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .performance },
time_origin: std.time.Timer,
// if (Window.crossOriginIsolated) -> Resolution in isolated contexts: 5 microseconds

View File

@@ -78,13 +78,13 @@ pub const Event = struct {
pub fn get_target(self: *parser.Event, page: *Page) !?EventTargetUnion {
const et = try parser.eventTarget(self);
if (et == null) return null;
return try EventTarget.toInterface(self, et.?, page);
return try EventTarget.toInterface(et.?, page);
}
pub fn get_currentTarget(self: *parser.Event, page: *Page) !?EventTargetUnion {
const et = try parser.eventCurrentTarget(self);
if (et == null) return null;
return try EventTarget.toInterface(self, et.?, page);
return try EventTarget.toInterface(et.?, page);
}
pub fn get_eventPhase(self: *parser.Event) !u8 {

View File

@@ -56,13 +56,12 @@ pub const AbortSignal = struct {
const DEFAULT_REASON = "AbortError";
pub const prototype = *EventTarget;
proto: parser.EventTargetTBase = .{},
proto: parser.EventTargetTBase = .{ .internal_target_type = .abort_signal },
aborted: bool,
reason: ?[]const u8,
pub const init: AbortSignal = .{
.proto = .{},
.reason = null,
.aborted = false,
};

View File

@@ -26,7 +26,7 @@ pub const MediaQueryList = struct {
// Extend libdom event target for pure zig struct.
// This is not safe as it relies on a structure layout that isn't guaranteed
base: parser.EventTargetTBase = parser.EventTargetTBase{},
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .media_query_list },
matches: bool,
media: []const u8,

View File

@@ -45,7 +45,7 @@ pub const Window = struct {
pub const prototype = *EventTarget;
// Extend libdom event target for pure zig struct.
base: parser.EventTargetTBase = parser.EventTargetTBase{},
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .window },
document: *parser.DocumentHTML,
target: []const u8 = "",

View File

@@ -779,8 +779,13 @@ pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 {
pub const EventTargetTBase = extern struct {
const Self = @This();
const InternalType = enum(u32) {
libdom = 0,
libdom_node = 0,
plain = 1,
abort_signal = 2,
xhr = 3,
window = 4,
performance = 5,
media_query_list = 6,
};
vtable: ?*const c.struct_dom_event_target_vtable = &c.struct_dom_event_target_vtable{
@@ -802,7 +807,7 @@ pub const EventTargetTBase = extern struct {
refcnt: u32 = 0,
eti: c.dom_event_target_internal = c.dom_event_target_internal{ .listeners = null },
internal_target_type: InternalType = .libdom,
internal_target_type: InternalType,
pub fn add_event_listener(et: [*c]c.dom_event_target, t: [*c]c.dom_string, l: ?*c.struct_dom_event_listener, capture: bool) callconv(.C) c.dom_exception {
const self = @as(*Self, @ptrCast(et));

View File

@@ -31,7 +31,7 @@ pub const XMLHttpRequestEventTarget = struct {
pub const prototype = *EventTarget;
// Extend libdom event target for pure zig struct.
base: parser.EventTargetTBase = parser.EventTargetTBase{},
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .xhr },
onloadstart_cbk: ?Function = null,
onprogress_cbk: ?Function = null,