From 293790bb9336961a5c7b0e38fd9f254146eee8d0 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Wed, 17 Apr 2024 15:51:06 +0200 Subject: [PATCH] handle listeners events removing themselves --- src/events/event_target.c | 10 +++++++++- src/utils/list.h | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/events/event_target.c b/src/events/event_target.c index f05affde..67a4d134 100644 --- a/src/events/event_target.c +++ b/src/events/event_target.c @@ -241,9 +241,17 @@ dom_exception _dom_event_target_dispatch(dom_event_target *et, * break */ if (evt->stop_now == true) break; + + // A listener can modify the event target listeners list + // during the loop. At this stage, `le` can be removed from + // the list and its memory freed. + // First we need to detect if `le` still exists. + if (!list_has((struct list_entry *)eti->listeners, (struct list_entry *)le)) { + // `le` has been deleted. + break; + } } } - le = (struct listener_entry *) le->list.next; } while (le != eti->listeners); } diff --git a/src/utils/list.h b/src/utils/list.h index 6e3ba209..ba973f21 100644 --- a/src/utils/list.h +++ b/src/utils/list.h @@ -13,6 +13,7 @@ #define dom_utils_list_h_ #include +#include struct list_entry { struct list_entry *prev; @@ -58,4 +59,21 @@ static inline void list_del(struct list_entry *ent) ent->next = ent; } +/** + * Detect if an entry is in the list + * + * \param entry The entry need to be deleted from the list + */ +static inline bool list_has(struct list_entry *head, struct list_entry *ent) +{ + struct list_entry *cur = head; + do { + if (cur == ent) { + return true; + } + cur = cur->next; + } while (cur != head); + return false; +} + #endif