mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Merge pull request #1763 from lightpanda-io/has_direct_listener
Add a hasDirectListeners to EventManager
This commit is contained in:
@@ -365,6 +365,29 @@ fn getFunction(handler: anytype, local: *const js.Local) ?js.Function {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if there are any listeners for a direct dispatch (non-DOM target).
|
||||||
|
/// Use this to avoid creating an event when there are no listeners.
|
||||||
|
pub fn hasDirectListeners(self: *EventManager, target: *EventTarget, typ: []const u8, handler: anytype) bool {
|
||||||
|
if (hasHandler(handler)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return self.lookup.get(.{
|
||||||
|
.event_target = @intFromPtr(target),
|
||||||
|
.type_string = .wrap(typ),
|
||||||
|
}) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hasHandler(handler: anytype) bool {
|
||||||
|
const ti = @typeInfo(@TypeOf(handler));
|
||||||
|
if (ti == .null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ti == .optional) {
|
||||||
|
return handler != null;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
fn dispatchNode(self: *EventManager, target: *Node, event: *Event, comptime opts: DispatchOpts) !void {
|
fn dispatchNode(self: *EventManager, target: *Node, event: *Event, comptime opts: DispatchOpts) !void {
|
||||||
const ShadowRoot = @import("webapi/ShadowRoot.zig");
|
const ShadowRoot = @import("webapi/ShadowRoot.zig");
|
||||||
|
|
||||||
|
|||||||
@@ -791,24 +791,19 @@ fn _documentIsComplete(self: *Page) !void {
|
|||||||
try self.dispatchLoad();
|
try self.dispatchLoad();
|
||||||
|
|
||||||
// Dispatch window.load event.
|
// Dispatch window.load event.
|
||||||
const event = try Event.initTrusted(comptime .wrap("load"), .{}, self);
|
const window_target = self.window.asEventTarget();
|
||||||
// This event is weird, it's dispatched directly on the window, but
|
if (self._event_manager.hasDirectListeners(window_target, "load", self.window._on_load)) {
|
||||||
// with the document as the target.
|
const event = try Event.initTrusted(comptime .wrap("load"), .{}, self);
|
||||||
event._target = self.document.asEventTarget();
|
// This event is weird, it's dispatched directly on the window, but
|
||||||
try self._event_manager.dispatchDirect(
|
// with the document as the target.
|
||||||
self.window.asEventTarget(),
|
event._target = self.document.asEventTarget();
|
||||||
event,
|
try self._event_manager.dispatchDirect(window_target, event, self.window._on_load, .{ .inject_target = false, .context = "page load" });
|
||||||
self.window._on_load,
|
}
|
||||||
.{ .inject_target = false, .context = "page load" },
|
|
||||||
);
|
|
||||||
|
|
||||||
const pageshow_event = (try PageTransitionEvent.initTrusted(comptime .wrap("pageshow"), .{}, self)).asEvent();
|
if (self._event_manager.hasDirectListeners(window_target, "pageshow", self.window._on_pageshow)) {
|
||||||
try self._event_manager.dispatchDirect(
|
const pageshow_event = (try PageTransitionEvent.initTrusted(comptime .wrap("pageshow"), .{}, self)).asEvent();
|
||||||
self.window.asEventTarget(),
|
try self._event_manager.dispatchDirect(window_target, pageshow_event, self.window._on_pageshow, .{ .context = "page show" });
|
||||||
pageshow_event,
|
}
|
||||||
self.window._on_pageshow,
|
|
||||||
.{ .context = "page show" },
|
|
||||||
);
|
|
||||||
|
|
||||||
self.notifyParentLoadComplete();
|
self.notifyParentLoadComplete();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,13 +76,11 @@ pub fn abort(self: *AbortSignal, reason_: ?Reason, page: *Page) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch abort event
|
// Dispatch abort event
|
||||||
const event = try Event.initTrusted(comptime .wrap("abort"), .{}, page);
|
const target = self.asEventTarget();
|
||||||
try page._event_manager.dispatchDirect(
|
if (page._event_manager.hasDirectListeners(target, "abort", self._on_abort)) {
|
||||||
self.asEventTarget(),
|
const event = try Event.initTrusted(comptime .wrap("abort"), .{}, page);
|
||||||
event,
|
try page._event_manager.dispatchDirect(target, event, self._on_abort, .{ .context = "abort signal" });
|
||||||
self._on_abort,
|
}
|
||||||
.{ .context = "abort signal" },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static method to create an already-aborted signal
|
// Static method to create an already-aborted signal
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ pub fn format(self: *EventTarget, writer: *std.Io.Writer) !void {
|
|||||||
.screen => writer.writeAll("<Screen>"),
|
.screen => writer.writeAll("<Screen>"),
|
||||||
.screen_orientation => writer.writeAll("<ScreenOrientation>"),
|
.screen_orientation => writer.writeAll("<ScreenOrientation>"),
|
||||||
.visual_viewport => writer.writeAll("<VisualViewport>"),
|
.visual_viewport => writer.writeAll("<VisualViewport>"),
|
||||||
|
.file_reader => writer.writeAll("<FileReader>"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,13 +79,11 @@ fn goInner(delta: i32, page: *Page) !void {
|
|||||||
|
|
||||||
if (entry._url) |url| {
|
if (entry._url) |url| {
|
||||||
if (try page.isSameOrigin(url)) {
|
if (try page.isSameOrigin(url)) {
|
||||||
const event = (try PopStateEvent.initTrusted(comptime .wrap("popstate"), .{ .state = entry._state.value }, page)).asEvent();
|
const target = page.window.asEventTarget();
|
||||||
try page._event_manager.dispatchDirect(
|
if (page._event_manager.hasDirectListeners(target, "popstate", page.window._on_popstate)) {
|
||||||
page.window.asEventTarget(),
|
const event = (try PopStateEvent.initTrusted(comptime .wrap("popstate"), .{ .state = entry._state.value }, page)).asEvent();
|
||||||
event,
|
try page._event_manager.dispatchDirect(target, event, page.window._on_popstate, .{ .context = "Pop State" });
|
||||||
page.window._on_popstate,
|
}
|
||||||
.{ .context = "Pop State" },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,23 +122,21 @@ const PostMessageCallback = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = (MessageEvent.initTrusted(comptime .wrap("message"), .{
|
const target = self.port.asEventTarget();
|
||||||
.data = self.message,
|
if (page._event_manager.hasDirectListeners(target, "message", self.port._on_message)) {
|
||||||
.origin = "",
|
const event = (MessageEvent.initTrusted(comptime .wrap("message"), .{
|
||||||
.source = null,
|
.data = self.message,
|
||||||
}, page) catch |err| {
|
.origin = "",
|
||||||
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
|
.source = null,
|
||||||
return null;
|
}, page) catch |err| {
|
||||||
}).asEvent();
|
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
|
||||||
|
return null;
|
||||||
|
}).asEvent();
|
||||||
|
|
||||||
page._event_manager.dispatchDirect(
|
page._event_manager.dispatchDirect(target, event, self.port._on_message, .{ .context = "MessagePort message" }) catch |err| {
|
||||||
self.port.asEventTarget(),
|
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
|
||||||
event,
|
};
|
||||||
self.port._on_message,
|
}
|
||||||
.{ .context = "MessagePort message" },
|
|
||||||
) catch |err| {
|
|
||||||
log.err(.dom, "MessagePort.postMessage", .{ .err = err });
|
|
||||||
};
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,17 +551,14 @@ pub fn unhandledPromiseRejection(self: *Window, rejection: js.PromiseRejection,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = (try @import("event/PromiseRejectionEvent.zig").init("unhandledrejection", .{
|
const target = self.asEventTarget();
|
||||||
.reason = if (rejection.reason()) |r| try r.temp() else null,
|
if (page._event_manager.hasDirectListeners(target, "unhandledrejection", self._on_unhandled_rejection)) {
|
||||||
.promise = try rejection.promise().temp(),
|
const event = (try @import("event/PromiseRejectionEvent.zig").init("unhandledrejection", .{
|
||||||
}, page)).asEvent();
|
.reason = if (rejection.reason()) |r| try r.temp() else null,
|
||||||
|
.promise = try rejection.promise().temp(),
|
||||||
try page._event_manager.dispatchDirect(
|
}, page)).asEvent();
|
||||||
self.asEventTarget(),
|
try page._event_manager.dispatchDirect(target, event, self._on_unhandled_rejection, .{ .context = "window.unhandledrejection" });
|
||||||
event,
|
}
|
||||||
self._on_unhandled_rejection,
|
|
||||||
.{ .inject_target = true, .context = "window.unhandledrejection" },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScheduleOpts = struct {
|
const ScheduleOpts = struct {
|
||||||
|
|||||||
@@ -508,13 +508,11 @@ fn stateChanged(self: *XMLHttpRequest, state: ReadyState, page: *Page) !void {
|
|||||||
|
|
||||||
self._ready_state = state;
|
self._ready_state = state;
|
||||||
|
|
||||||
const event = try Event.initTrusted(.wrap("readystatechange"), .{}, page);
|
const target = self.asEventTarget();
|
||||||
try page._event_manager.dispatchDirect(
|
if (page._event_manager.hasDirectListeners(target, "readystatechange", self._on_ready_state_change)) {
|
||||||
self.asEventTarget(),
|
const event = try Event.initTrusted(.wrap("readystatechange"), .{}, page);
|
||||||
event,
|
try page._event_manager.dispatchDirect(target, event, self._on_ready_state_change, .{ .context = "XHR state change" });
|
||||||
self._on_ready_state_change,
|
}
|
||||||
.{ .context = "XHR state change" },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseMethod(method: []const u8) !Http.Method {
|
fn parseMethod(method: []const u8) !Http.Method {
|
||||||
|
|||||||
Reference in New Issue
Block a user