mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 07:03:29 +00:00
Add deinit for EventTarget (eventTargetRemoveAllEventListeners)
And unify the way allocator is used on eventTarget add/remove listener Signed-off-by: Francis Bouvier <francis@lightpanda.io>
This commit is contained in:
@@ -50,14 +50,11 @@ pub const EventTarget = struct {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: this allocation will be removed either if removeEventListener
|
|
||||||
// or at EventTarget deinit
|
|
||||||
const cbk_ptr = try alloc.create(Callback);
|
|
||||||
cbk_ptr.* = cbk;
|
|
||||||
try parser.eventTargetAddEventListener(
|
try parser.eventTargetAddEventListener(
|
||||||
self,
|
self,
|
||||||
|
alloc,
|
||||||
eventType,
|
eventType,
|
||||||
cbk_ptr,
|
cbk,
|
||||||
capture orelse false,
|
capture orelse false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -84,26 +81,21 @@ pub const EventTarget = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove listener
|
// remove listener
|
||||||
const cbk_handler = try parser.eventTargetRemoveEventListener(
|
try parser.eventTargetRemoveEventListener(
|
||||||
self,
|
self,
|
||||||
|
alloc,
|
||||||
eventType,
|
eventType,
|
||||||
lst.?,
|
lst.?,
|
||||||
capture orelse false,
|
capture orelse false,
|
||||||
);
|
);
|
||||||
if (cbk_handler) |cbk_ptr| {
|
|
||||||
cbk_ptr.deinit(alloc);
|
|
||||||
alloc.destroy(cbk_ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _dispatchEvent(self: *parser.EventTarget, event: *parser.Event) !bool {
|
pub fn _dispatchEvent(self: *parser.EventTarget, event: *parser.Event) !bool {
|
||||||
return try parser.eventTargetDispatchEvent(self, event);
|
return try parser.eventTargetDispatchEvent(self, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(_: *parser.EventTarget, _: std.mem.Allocator) void {
|
pub fn deinit(self: *parser.EventTarget, alloc: std.mem.Allocator) void {
|
||||||
// TODO:
|
parser.eventTargetRemoveAllEventListeners(self, alloc) catch unreachable;
|
||||||
// - deinit and destroy all cbk_handler
|
|
||||||
// - remove all listeners
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -444,8 +444,6 @@ pub fn eventPreventDefault(evt: *Event) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EventHandler
|
// EventHandler
|
||||||
pub const EventHandler = fn (?*Event, ?*anyopaque) callconv(.C) void;
|
|
||||||
|
|
||||||
fn event_handler_cbk(data: *anyopaque) *Callback {
|
fn event_handler_cbk(data: *anyopaque) *Callback {
|
||||||
const ptr: *align(@alignOf(*Callback)) anyopaque = @alignCast(data);
|
const ptr: *align(@alignOf(*Callback)) anyopaque = @alignCast(data);
|
||||||
return @as(*Callback, @ptrCast(ptr));
|
return @as(*Callback, @ptrCast(ptr));
|
||||||
@@ -458,16 +456,16 @@ const event_handler = struct {
|
|||||||
func.call(.{event}) catch unreachable;
|
func.call(.{event}) catch unreachable;
|
||||||
// NOTE: we can not call func.deinit here
|
// NOTE: we can not call func.deinit here
|
||||||
// b/c the handler can be called several times
|
// b/c the handler can be called several times
|
||||||
// as the event goes through the ancestors
|
// either on this dispatch event or in anoter one
|
||||||
// TODO: check the event phase to call func.deinit and free func
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.handle;
|
}.handle;
|
||||||
|
|
||||||
// EventListener
|
// EventListener
|
||||||
pub const EventListener = c.dom_event_listener;
|
pub const EventListener = c.dom_event_listener;
|
||||||
|
const EventListenerEntry = c.listener_entry;
|
||||||
|
|
||||||
pub fn eventListenerGetData(lst: *EventListener) ?*anyopaque {
|
fn eventListenerGetData(lst: *EventListener) ?*anyopaque {
|
||||||
return c.dom_event_listener_get_data(lst);
|
return c.dom_event_listener_get_data(lst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,7 +484,6 @@ pub fn eventTargetHasListener(
|
|||||||
) !?*EventListener {
|
) !?*EventListener {
|
||||||
const str = try strFromData(typ);
|
const str = try strFromData(typ);
|
||||||
|
|
||||||
const EventListenerEntry = c.listener_entry;
|
|
||||||
var current: ?*EventListenerEntry = null;
|
var current: ?*EventListenerEntry = null;
|
||||||
var next: ?*EventListenerEntry = undefined;
|
var next: ?*EventListenerEntry = undefined;
|
||||||
var lst: ?*EventListener = undefined;
|
var lst: ?*EventListener = undefined;
|
||||||
@@ -504,14 +501,16 @@ pub fn eventTargetHasListener(
|
|||||||
try DOMErr(err);
|
try DOMErr(err);
|
||||||
|
|
||||||
if (lst) |listener| {
|
if (lst) |listener| {
|
||||||
// the EventTarget has a listener for this event type,
|
// the EventTarget has a listener for this event type
|
||||||
// let's check if the callback is the same
|
// and capture property,
|
||||||
|
// let's check if the callback handler is the same
|
||||||
defer c.dom_event_listener_unref(listener);
|
defer c.dom_event_listener_unref(listener);
|
||||||
const data = eventListenerGetData(listener);
|
const data = eventListenerGetData(listener);
|
||||||
if (data) |d| {
|
if (data) |d| {
|
||||||
const cbk = event_handler_cbk(d);
|
const cbk = event_handler_cbk(d);
|
||||||
if (cbk_id == cbk.id())
|
if (cbk_id == cbk.id()) {
|
||||||
return lst;
|
return lst;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,34 +528,91 @@ pub fn eventTargetHasListener(
|
|||||||
|
|
||||||
pub fn eventTargetAddEventListener(
|
pub fn eventTargetAddEventListener(
|
||||||
et: *EventTarget,
|
et: *EventTarget,
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
typ: []const u8,
|
typ: []const u8,
|
||||||
cbk_ptr: *Callback,
|
cbk: Callback,
|
||||||
capture: bool,
|
capture: bool,
|
||||||
) !void {
|
) !void {
|
||||||
const s = try strFromData(typ);
|
// this allocation will be removed either on
|
||||||
|
// eventTargetRemoveEventListener or eventTargetRemoveAllEventListeners
|
||||||
|
const cbk_ptr = try alloc.create(Callback);
|
||||||
|
cbk_ptr.* = cbk;
|
||||||
|
|
||||||
const ctx = @as(*anyopaque, @ptrCast(cbk_ptr));
|
const ctx = @as(*anyopaque, @ptrCast(cbk_ptr));
|
||||||
var listener: ?*EventListener = undefined;
|
var listener: ?*EventListener = undefined;
|
||||||
const errLst = c.dom_event_listener_create(event_handler, ctx, &listener);
|
const errLst = c.dom_event_listener_create(event_handler, ctx, &listener);
|
||||||
try DOMErr(errLst);
|
try DOMErr(errLst);
|
||||||
|
defer c.dom_event_listener_unref(listener);
|
||||||
|
|
||||||
|
const s = try strFromData(typ);
|
||||||
const err = eventTargetVtable(et).add_event_listener.?(et, s, listener, capture);
|
const err = eventTargetVtable(et).add_event_listener.?(et, s, listener, capture);
|
||||||
try DOMErr(err);
|
try DOMErr(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eventTargetRemoveEventListener(
|
pub fn eventTargetRemoveEventListener(
|
||||||
et: *EventTarget,
|
et: *EventTarget,
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
typ: []const u8,
|
typ: []const u8,
|
||||||
lst: *EventListener,
|
lst: *EventListener,
|
||||||
capture: bool,
|
capture: bool,
|
||||||
) !?*Callback {
|
) !void {
|
||||||
const data = eventListenerGetData(lst);
|
const data = eventListenerGetData(lst);
|
||||||
var cbk_ptr: ?*Callback = null;
|
// free cbk allocation made on eventTargetAddEventListener
|
||||||
if (data) |d| {
|
if (data) |d| {
|
||||||
cbk_ptr = event_handler_cbk(d);
|
const cbk_ptr = event_handler_cbk(d);
|
||||||
|
cbk_ptr.deinit(alloc);
|
||||||
|
alloc.destroy(cbk_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = try strFromData(typ);
|
const s = try strFromData(typ);
|
||||||
const err = eventTargetVtable(et).remove_event_listener.?(et, s, lst, capture);
|
const err = eventTargetVtable(et).remove_event_listener.?(et, s, lst, capture);
|
||||||
try DOMErr(err);
|
try DOMErr(err);
|
||||||
return cbk_ptr;
|
}
|
||||||
|
|
||||||
|
pub fn eventTargetRemoveAllEventListeners(
|
||||||
|
et: *EventTarget,
|
||||||
|
alloc: std.mem.Allocator,
|
||||||
|
) !void {
|
||||||
|
var next: ?*EventListenerEntry = undefined;
|
||||||
|
var lst: ?*EventListener = undefined;
|
||||||
|
|
||||||
|
// iterate over the EventTarget's listeners
|
||||||
|
while (true) {
|
||||||
|
const errIter = eventTargetVtable(et).iter_event_listener.?(
|
||||||
|
et,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
&next,
|
||||||
|
&lst,
|
||||||
|
);
|
||||||
|
try DOMErr(errIter);
|
||||||
|
|
||||||
|
if (lst) |listener| {
|
||||||
|
defer c.dom_event_listener_unref(listener);
|
||||||
|
const data = eventListenerGetData(listener);
|
||||||
|
if (data) |d| {
|
||||||
|
// free cbk allocation made on eventTargetAddEventListener
|
||||||
|
const cbk = event_handler_cbk(d);
|
||||||
|
cbk.deinit(alloc);
|
||||||
|
alloc.destroy(cbk);
|
||||||
|
}
|
||||||
|
const err = eventTargetVtable(et).remove_event_listener.?(
|
||||||
|
et,
|
||||||
|
null,
|
||||||
|
lst,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
try DOMErr(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next == null) {
|
||||||
|
// no more listeners, end of the iteration
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// next iteration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool {
|
pub fn eventTargetDispatchEvent(et: *EventTarget, event: *Event) !bool {
|
||||||
|
|||||||
2
vendor/jsruntime-lib
vendored
2
vendor/jsruntime-lib
vendored
Submodule vendor/jsruntime-lib updated: 637cd3a344...2af9e9b7fc
Reference in New Issue
Block a user