Skip to content

Commit 47c14db

Browse files
authored
Merge pull request #577 from lightpanda-io/unified_intrusive_events
Unify the Zig and JS events using an intrusive node.
2 parents f0e0650 + 1f0d192 commit 47c14db

File tree

7 files changed

+142
-220
lines changed

7 files changed

+142
-220
lines changed

src/browser/browser.zig

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ pub const Page = struct {
229229

230230
renderer: FlatRenderer,
231231

232+
window_clicked_event_node: parser.EventNode,
233+
232234
scope: *Env.Scope,
233235

234236
// current_script is the script currently evaluated by the page.
@@ -245,6 +247,7 @@ pub const Page = struct {
245247
.url = URL.empty,
246248
.session = session,
247249
.renderer = FlatRenderer.init(arena),
250+
.window_clicked_event_node = .{ .func = windowClicked },
248251
.state = .{
249252
.arena = arena,
250253
.document = null,
@@ -400,12 +403,10 @@ pub const Page = struct {
400403
self.doc = doc;
401404

402405
const document_element = (try parser.documentGetDocumentElement(doc)) orelse return error.DocumentElementError;
403-
try parser.eventTargetAddZigListener(
406+
try parser.eventTargetAddEventListener(
404407
parser.toEventTarget(parser.Element, document_element),
405-
arena,
406408
"click",
407-
windowClicked,
408-
self,
409+
&self.window_clicked_event_node,
409410
false,
410411
);
411412

@@ -675,8 +676,8 @@ pub const Page = struct {
675676
_ = try parser.elementDispatchEvent(element, @ptrCast(event));
676677
}
677678

678-
fn windowClicked(ctx: *anyopaque, event: *parser.Event) void {
679-
const self: *Page = @alignCast(@ptrCast(ctx));
679+
fn windowClicked(node: *parser.EventNode, event: *parser.Event) void {
680+
const self: *Page = @fieldParentPtr("window_clicked_event_node", node);
680681
self._windowClicked(event) catch |err| {
681682
log.err("window click handler: {}", .{err});
682683
};

src/browser/dom/event_target.zig

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub const EventTarget = struct {
4646

4747
pub fn _addEventListener(
4848
self: *parser.EventTarget,
49-
eventType: []const u8,
49+
typ: []const u8,
5050
cbk: Env.Callback,
5151
capture: ?bool,
5252
state: *SessionState,
@@ -56,37 +56,36 @@ pub const EventTarget = struct {
5656
// check if event target has already this listener
5757
const lst = try parser.eventTargetHasListener(
5858
self,
59-
eventType,
59+
typ,
6060
capture orelse false,
6161
cbk.id,
6262
);
6363
if (lst != null) {
6464
return;
6565
}
6666

67+
const eh = try EventHandler.init(state.arena, try cbk.withThis(self));
68+
6769
try parser.eventTargetAddEventListener(
6870
self,
69-
state.arena,
70-
eventType,
71-
EventHandler,
72-
.{ .cbk = cbk },
71+
typ,
72+
&eh.node,
7373
capture orelse false,
7474
);
7575
}
7676

7777
pub fn _removeEventListener(
7878
self: *parser.EventTarget,
79-
eventType: []const u8,
79+
typ: []const u8,
8080
cbk: Env.Callback,
8181
capture: ?bool,
82-
state: *SessionState,
8382
// TODO: hanle EventListenerOptions
8483
// see #https://github.com/lightpanda-io/jsruntime-lib/issues/114
8584
) !void {
8685
// check if event target has already this listener
8786
const lst = try parser.eventTargetHasListener(
8887
self,
89-
eventType,
88+
typ,
9089
capture orelse false,
9190
cbk.id,
9291
);
@@ -97,8 +96,7 @@ pub const EventTarget = struct {
9796
// remove listener
9897
try parser.eventTargetRemoveEventListener(
9998
self,
100-
state.arena,
101-
eventType,
99+
typ,
102100
lst.?,
103101
capture orelse false,
104102
);

src/browser/dom/mutation_observer.zig

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -59,56 +59,45 @@ pub const MutationObserver = struct {
5959
.node = node,
6060
.options = options,
6161
.mutation_observer = self,
62+
.event_node = .{ .id = self.cbk.id, .func = Observer.handle },
6263
};
6364

64-
const arena = self.arena;
65-
6665
// register node's events
6766
if (options.childList or options.subtree) {
68-
try parser.eventTargetAddZigListener(
67+
try parser.eventTargetAddEventListener(
6968
parser.toEventTarget(parser.Node, node),
70-
arena,
7169
"DOMNodeInserted",
72-
Observer.handle,
73-
observer,
70+
&observer.event_node,
7471
false,
7572
);
76-
try parser.eventTargetAddZigListener(
73+
try parser.eventTargetAddEventListener(
7774
parser.toEventTarget(parser.Node, node),
78-
arena,
7975
"DOMNodeRemoved",
80-
Observer.handle,
81-
observer,
76+
&observer.event_node,
8277
false,
8378
);
8479
}
8580
if (options.attr()) {
86-
try parser.eventTargetAddZigListener(
81+
try parser.eventTargetAddEventListener(
8782
parser.toEventTarget(parser.Node, node),
88-
arena,
8983
"DOMAttrModified",
90-
Observer.handle,
91-
observer,
84+
&observer.event_node,
9285
false,
9386
);
9487
}
9588
if (options.cdata()) {
96-
try parser.eventTargetAddZigListener(
89+
try parser.eventTargetAddEventListener(
9790
parser.toEventTarget(parser.Node, node),
98-
arena,
9991
"DOMCharacterDataModified",
100-
Observer.handle,
101-
observer,
92+
&observer.event_node,
10293
false,
10394
);
10495
}
10596
if (options.subtree) {
106-
try parser.eventTargetAddZigListener(
97+
try parser.eventTargetAddEventListener(
10798
parser.toEventTarget(parser.Node, node),
108-
arena,
10999
"DOMSubtreeModified",
110-
Observer.handle,
111-
observer,
100+
&observer.event_node,
112101
false,
113102
);
114103
}
@@ -221,6 +210,8 @@ const Observer = struct {
221210
// and batch the mutation records.
222211
mutation_observer: *MutationObserver,
223212

213+
event_node: parser.EventNode,
214+
224215
fn appliesTo(o: *const Observer, target: *parser.Node) bool {
225216
// mutation on any target is always ok.
226217
if (o.options.subtree) {
@@ -250,9 +241,9 @@ const Observer = struct {
250241
return false;
251242
}
252243

253-
fn handle(ctx: *anyopaque, event: *parser.Event) void {
254-
// retrieve the observer from the data.
255-
var self: *Observer = @alignCast(@ptrCast(ctx));
244+
fn handle(en: *parser.EventNode, event: *parser.Event) void {
245+
const self: *Observer = @fieldParentPtr("event_node", en);
246+
256247
var mutation_observer = self.mutation_observer;
257248

258249
const node = blk: {

src/browser/events/event.zig

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818

1919
const std = @import("std");
20+
const Allocator = std.mem.Allocator;
2021

2122
const parser = @import("../netsurf.zig");
2223
const Callback = @import("../env.zig").Callback;
@@ -136,14 +137,35 @@ pub const Event = struct {
136137
};
137138

138139
pub const EventHandler = struct {
139-
fn handle(event: ?*parser.Event, data: *const parser.JSEventHandlerData) void {
140+
callback: Callback,
141+
node: parser.EventNode,
142+
143+
pub fn init(allocator: Allocator, callback: Callback) !*EventHandler {
144+
const eh = try allocator.create(EventHandler);
145+
eh.* = .{
146+
.callback = callback,
147+
.node = .{
148+
.id = callback.id,
149+
.func = handle,
150+
},
151+
};
152+
return eh;
153+
}
154+
155+
fn handle(node: *parser.EventNode, event: *parser.Event) void {
156+
const ievent = Event.toInterface(event) catch |err| {
157+
log.err("Event.toInterface: {}", .{err});
158+
return;
159+
};
160+
161+
const self: *EventHandler = @fieldParentPtr("node", node);
140162
var result: Callback.Result = undefined;
141-
data.cbk.tryCall(.{if (event) |evt| Event.toInterface(evt) catch unreachable else null}, &result) catch {
163+
self.callback.tryCall(.{ievent}, &result) catch {
142164
log.err("event handler error: {s}", .{result.exception});
143165
log.debug("stack:\n{s}", .{result.stack orelse "???"});
144166
};
145167
}
146-
}.handle;
168+
};
147169

148170
const testing = @import("../../testing.zig");
149171
test "Browser.Event" {

0 commit comments

Comments
 (0)