From 4f127c9de3a8490fe80c121690da148b3c21d86c Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Mon, 15 Sep 2025 22:24:35 +0800 Subject: [PATCH 1/3] Bubble events to the Window --- src/browser/dom/event_target.zig | 18 ++++++++++++++++-- src/browser/netsurf.zig | 2 +- src/tests/events/custom.html | 8 ++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/browser/dom/event_target.zig b/src/browser/dom/event_target.zig index 3d239629..c214cf48 100644 --- a/src/browser/dom/event_target.zig +++ b/src/browser/dom/event_target.zig @@ -148,8 +148,22 @@ pub const EventTarget = struct { ); } - pub fn _dispatchEvent(self: *parser.EventTarget, event: *parser.Event) !bool { - return try parser.eventTargetDispatchEvent(self, event); + pub fn _dispatchEvent(self: *parser.EventTarget, event: *parser.Event, page: *Page) !bool { + const res = try parser.eventTargetDispatchEvent(self, event); + + // TODO: If we get this working, we should also create a getter to check + // stopPropagation and not bubble to window if true. + if (!parser.eventBubbles(event)) { + return res; + } + + // I think this mutates `event`, which means any JavaScript that captured + // it will be mutated incorrectly. + const Window = @import("../html/window.zig").Window; + return parser.eventTargetDispatchEvent( + parser.toEventTarget(Window, &page.window), + event, + ); } }; diff --git a/src/browser/netsurf.zig b/src/browser/netsurf.zig index 01aeb82c..d33f0790 100644 --- a/src/browser/netsurf.zig +++ b/src/browser/netsurf.zig @@ -604,7 +604,7 @@ fn eventTargetVtable(et: *EventTarget) c.dom_event_target_vtable { return @as([*c]const c.dom_event_target_vtable, @ptrCast(vtable_aligned)).*; } -pub inline fn toEventTarget(comptime T: type, v: *T) *EventTarget { +pub 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)); diff --git a/src/tests/events/custom.html b/src/tests/events/custom.html index e749fe05..ed7e0faf 100644 --- a/src/tests/events/custom.html +++ b/src/tests/events/custom.html @@ -13,4 +13,12 @@ el.dispatchEvent(new CustomEvent('c2', {detail: {over: 9000}})); testing.expectEqual("c2-9000", capture); + + let window_calls = 0; + window.addEventListener('c1', () => { + window_calls += 1; + }); + + el.dispatchEvent(new CustomEvent('c1', {bubbles: true})); + testing.expectEqual(1, window_calls); From 1ba542fb3ba8648776f1fe1dbc88518f759b1b7e Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Tue, 16 Sep 2025 10:26:51 +0800 Subject: [PATCH 2/3] use redispatch, check for stopped --- src/browser/dom/event_target.zig | 13 +++---------- src/browser/netsurf.zig | 7 +++++++ vendor/netsurf/libdom | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/browser/dom/event_target.zig b/src/browser/dom/event_target.zig index c214cf48..acaf5c3f 100644 --- a/src/browser/dom/event_target.zig +++ b/src/browser/dom/event_target.zig @@ -151,19 +151,12 @@ pub const EventTarget = struct { pub fn _dispatchEvent(self: *parser.EventTarget, event: *parser.Event, page: *Page) !bool { const res = try parser.eventTargetDispatchEvent(self, event); - // TODO: If we get this working, we should also create a getter to check - // stopPropagation and not bubble to window if true. - if (!parser.eventBubbles(event)) { + if (!parser.eventBubbles(event) or parser.eventIsStopped(event)) { return res; } - // I think this mutates `event`, which means any JavaScript that captured - // it will be mutated incorrectly. - const Window = @import("../html/window.zig").Window; - return parser.eventTargetDispatchEvent( - parser.toEventTarget(Window, &page.window), - event, - ); + try page.window.dispatchForDocumentTarget(event); + return true; } }; diff --git a/src/browser/netsurf.zig b/src/browser/netsurf.zig index d33f0790..aa20be60 100644 --- a/src/browser/netsurf.zig +++ b/src/browser/netsurf.zig @@ -517,6 +517,13 @@ pub fn eventStopPropagation(evt: *Event) void { std.debug.assert(err == c.DOM_NO_ERR); } +pub fn eventIsStopped(evt: *Event) bool { + var res: bool = undefined; + const err = c._dom_event_is_stopped(evt, &res); + std.debug.assert(err == c.DOM_NO_ERR); + return res; +} + pub fn eventStopImmediatePropagation(evt: *Event) void { const err = c._dom_event_stop_immediate_propagation(evt); std.debug.assert(err == c.DOM_NO_ERR); diff --git a/vendor/netsurf/libdom b/vendor/netsurf/libdom index 0a6ba2c7..b7db06f5 160000 --- a/vendor/netsurf/libdom +++ b/vendor/netsurf/libdom @@ -1 +1 @@ -Subproject commit 0a6ba2c73d6d673dfeadf7070167c0ce9d945721 +Subproject commit b7db06f58364aa01f8e3df920c28f16e62f6f8d1 From 1b73691c696744d2dd8d28cc732eaaccd8578b67 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Tue, 16 Sep 2025 18:21:16 +0800 Subject: [PATCH 3/3] update libdom dep --- vendor/netsurf/libdom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/netsurf/libdom b/vendor/netsurf/libdom index b7db06f5..a2513179 160000 --- a/vendor/netsurf/libdom +++ b/vendor/netsurf/libdom @@ -1 +1 @@ -Subproject commit b7db06f58364aa01f8e3df920c28f16e62f6f8d1 +Subproject commit a2513179286ce82bbae53123b82f64fe45f82e05