mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-30 17:25:58 -04:00
webapi: support onclick property handler on Window and Document
Fixes the failing test in WPT /dom/events/handler-count.html?window and ?document (1/2 -> 2/2 each): setting `window.onclick` or `document.onclick` did nothing, because neither interface exposed the accessor — the assignment created an inert expando and the handler never fired for clicks bubbling up from the page. Both now store the handler in the frame's attribute-listener map (the same mechanism as element and ShadowRoot property handlers), which the dispatch propagation path already consults for any event target. Non-callable values clear the handler per [LegacyTreatNonObjectAsNull]. Coverage: /dom/events/handler-count.html?window 1/2 -> 2/2, /dom/events/handler-count.html?document 1/2 -> 2/2. No regressions across /dom/events. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Karl Seguin
parent
86f9059f3f
commit
a0418aed5c
@@ -21,6 +21,7 @@ const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
const Frame = @import("../Frame.zig");
|
||||
const Window = @import("Window.zig");
|
||||
const URL = @import("../URL.zig");
|
||||
const idna = @import("../../sys/idna.zig");
|
||||
const public_suffix_list = @import("../../data/public_suffix_list.zig");
|
||||
@@ -89,6 +90,21 @@ pub fn setOnSelectionChange(self: *Document, listener: ?js.Function) !void {
|
||||
}
|
||||
}
|
||||
|
||||
// Stored in the frame's attribute-listener map (like element and ShadowRoot
|
||||
// property handlers), which the dispatch propagation path consults for any
|
||||
// event target.
|
||||
pub fn getOnClick(self: *Document, frame: *Frame) ?js.Function.Global {
|
||||
return frame._event_target_attr_listeners.get(.{ .target = self.asEventTarget(), .handler = .onclick });
|
||||
}
|
||||
|
||||
pub fn setOnClick(self: *Document, setter: ?Window.FunctionSetter, frame: *Frame) !void {
|
||||
if (Window.getFunctionFromSetter(setter)) |cb| {
|
||||
try frame._event_target_attr_listeners.put(frame.arena, .{ .target = self.asEventTarget(), .handler = .onclick }, cb);
|
||||
} else {
|
||||
_ = frame._event_target_attr_listeners.remove(.{ .target = self.asEventTarget(), .handler = .onclick });
|
||||
}
|
||||
}
|
||||
|
||||
pub const Type = union(enum) {
|
||||
generic,
|
||||
html: *HTMLDocument,
|
||||
@@ -1265,6 +1281,7 @@ pub const JsApi = struct {
|
||||
}
|
||||
|
||||
pub const onselectionchange = bridge.accessor(Document.getOnSelectionChange, Document.setOnSelectionChange, .{});
|
||||
pub const onclick = bridge.accessor(Document.getOnClick, Document.setOnClick, .{});
|
||||
pub const URL = bridge.accessor(Document.getURL, null, .{});
|
||||
pub const location = bridge.accessor(Document.getLocation, Document.setLocation, .{});
|
||||
pub const documentURI = bridge.accessor(Document.getURL, null, .{});
|
||||
|
||||
@@ -425,6 +425,21 @@ pub fn setOnScroll(self: *Window, setter: ?FunctionSetter) void {
|
||||
self._on_scroll = getFunctionFromSetter(setter);
|
||||
}
|
||||
|
||||
// Stored in the frame's attribute-listener map (like element and ShadowRoot
|
||||
// property handlers), which the dispatch propagation path consults for any
|
||||
// event target.
|
||||
pub fn getOnClick(self: *Window, frame: *Frame) ?js.Function.Global {
|
||||
return frame._event_target_attr_listeners.get(.{ .target = self.asEventTarget(), .handler = .onclick });
|
||||
}
|
||||
|
||||
pub fn setOnClick(self: *Window, setter: ?FunctionSetter, frame: *Frame) !void {
|
||||
if (getFunctionFromSetter(setter)) |cb| {
|
||||
try frame._event_target_attr_listeners.put(frame.arena, .{ .target = self.asEventTarget(), .handler = .onclick }, cb);
|
||||
} else {
|
||||
_ = frame._event_target_attr_listeners.remove(.{ .target = self.asEventTarget(), .handler = .onclick });
|
||||
}
|
||||
}
|
||||
|
||||
// The "window-reflecting body element event handler set" (HTML spec): these
|
||||
// event handlers of body and frameset elements are aliases for the Window's.
|
||||
// Returns the Window storage slot for the given content attribute name, or
|
||||
@@ -1159,6 +1174,7 @@ pub const JsApi = struct {
|
||||
pub const onfocus = bridge.accessor(Window.getOnFocus, Window.setOnFocus, .{});
|
||||
pub const onresize = bridge.accessor(Window.getOnResize, Window.setOnResize, .{});
|
||||
pub const onscroll = bridge.accessor(Window.getOnScroll, Window.setOnScroll, .{});
|
||||
pub const onclick = bridge.accessor(Window.getOnClick, Window.setOnClick, .{});
|
||||
pub const onmessage = bridge.accessor(Window.getOnMessage, Window.setOnMessage, .{});
|
||||
pub const onrejectionhandled = bridge.accessor(Window.getOnRejectionHandled, Window.setOnRejectionHandled, .{});
|
||||
pub const onunhandledrejection = bridge.accessor(Window.getOnUnhandledRejection, Window.setOnUnhandledRejection, .{});
|
||||
|
||||
Reference in New Issue
Block a user