Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/browser/dom/event_target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@ const nod = @import("node.zig");
pub const Union = union(enum) {
node: nod.Union,
xhr: *@import("../xhr/xhr.zig").XMLHttpRequest,
plain: *parser.EventTarget,
};

// EventTarget implementation
pub const EventTarget = struct {
pub const Self = parser.EventTarget;
pub const Exception = DOMException;

// 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 {
// libdom assumes that all event targets are libdom nodes. They are not.

Expand All @@ -44,6 +48,10 @@ pub const EventTarget = struct {
return .{ .node = .{ .Window = &page.window } };
}

if (try parser.eventTargetInternalType(et) == .plain) {
return .{ .plain = et };
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand keeping the PR focused is good. But, if the goal is to migrate AbortSignal and XMLHttpRequestEventTarget to this, then it might be worth including that change now. It's a good way to make sure the new field/behavior is capable of handling all know (and thus hopefully future) cases. Your call.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, Just wanted confirmation of the chosen solution first before doing the others.
Added the others and cleanup here: 14eeffd

// 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)) {
Expand All @@ -63,6 +71,11 @@ pub const EventTarget = struct {

// JS funcs
// --------
pub fn constructor(page: *Page) !*parser.EventTarget {
const et = try page.arena.create(EventTarget);
return @ptrCast(&et.base);
}

pub fn _addEventListener(
self: *parser.EventTarget,
typ: []const u8,
Expand Down Expand Up @@ -128,6 +141,10 @@ test "Browser.DOM.EventTarget" {
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
defer runner.deinit();

try runner.testCases(&.{
.{ "new EventTarget()", "[object EventTarget]" },
}, .{});

try runner.testCases(&.{
.{ "let content = document.getElementById('content')", "undefined" },
.{ "let para = document.getElementById('para')", "undefined" },
Expand Down
19 changes: 19 additions & 0 deletions src/browser/netsurf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,13 @@ pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool {
return res;
}

pub fn eventTargetInternalType(et: *EventTarget) !EventTargetTBase.InternalType {
var res: u32 = undefined;
const err = eventTargetVtable(et).internal_type.?(et, &res);
try DOMErr(err);
return @enumFromInt(res);
}

pub fn elementDispatchEvent(element: *Element, event: *Event) !bool {
const et: *EventTarget = toEventTarget(Element, element);
return eventTargetDispatchEvent(et, @ptrCast(event));
Expand All @@ -771,12 +778,17 @@ pub fn eventTargetTBaseFieldName(comptime T: type) ?[]const u8 {
// EventTargetBase is used to implement EventTarget for pure zig struct.
pub const EventTargetTBase = extern struct {
const Self = @This();
const InternalType = enum(u32) {
libdom = 0,
plain = 1,
};

vtable: ?*const c.struct_dom_event_target_vtable = &c.struct_dom_event_target_vtable{
.dispatch_event = dispatch_event,
.remove_event_listener = remove_event_listener,
.add_event_listener = add_event_listener,
.iter_event_listener = iter_event_listener,
.internal_type = internal_type,
},

// When we dispatch the event, we need to provide a target. In reality, the
Expand All @@ -790,6 +802,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,

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));
Expand Down Expand Up @@ -822,6 +835,12 @@ pub const EventTargetTBase = extern struct {
const self = @as(*Self, @ptrCast(et));
return c._dom_event_target_iter_event_listener(self.eti, t, capture, cur, next, l);
}

pub fn internal_type(et: [*c]c.dom_event_target, internal_type_: [*c]u32) callconv(.C) c.dom_exception {
const self = @as(*Self, @ptrCast(et));
internal_type_.* = @intFromEnum(self.internal_target_type);
return c.DOM_NO_ERR;
}
};

// MouseEvent
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2002,14 +2002,14 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
const info = v8.FunctionCallbackInfo.initFromV8(raw_info);
var caller = Caller(Self, State).init(info);
defer caller.deinit();

// See comment above. We generateConstructor on all types
// in order to create the FunctionTemplate, but there might
// not be an actual "constructor" function. So if someone
// does `new ClassName()` where ClassName doesn't have
// a constructor function, we'll return an error.
if (@hasDecl(Struct, "constructor") == false) {
const iso = caller.isolate;
log.warn(.js, "Illegal constructor call", .{ .name = @typeName(Struct) });
const js_exception = iso.throwException(createException(iso, "Illegal Constructor"));
info.getReturnValue().set(js_exception);
return;
Expand Down Expand Up @@ -3420,7 +3420,7 @@ fn valueToDetailString(arena: Allocator, value: v8.Value, isolate: v8.Isolate, v
if (debugValueToString(arena, value.castTo(v8.Object), isolate, v8_context)) |ds| {
return ds;
} else |err| {
log.err(.js, "debug serialize value", .{.err = err});
log.err(.js, "debug serialize value", .{ .err = err });
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion vendor/netsurf/libdom