From 4daec8f6e0fd6f8748c034c569d98ea1ce5fe3f4 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 18 Jun 2026 00:15:31 +0200 Subject: [PATCH] LibWeb: Use Event storage for MouseEvent relatedTarget Store MouseEvent's relatedTarget in the inherited Event field instead of keeping a second slot on MouseEvent. Event dispatch retargets and updates the inherited field while building the event path. The second slot left JS listeners observing stale or null relatedTarget values during mouse and pointer boundary events. Add coverage for boundary events between sibling elements. --- Libraries/LibWeb/UIEvents/MouseEvent.cpp | 12 ++------ Libraries/LibWeb/UIEvents/MouseEvent.h | 4 --- .../mouse-boundary-events-related-target.txt | 6 ++++ .../mouse-boundary-events-related-target.html | 28 +++++++++++++++++++ 4 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/UIEvents/mouse-boundary-events-related-target.txt create mode 100644 Tests/LibWeb/Text/input/UIEvents/mouse-boundary-events-related-target.html diff --git a/Libraries/LibWeb/UIEvents/MouseEvent.cpp b/Libraries/LibWeb/UIEvents/MouseEvent.cpp index 60b0b88dea..928bce024e 100644 --- a/Libraries/LibWeb/UIEvents/MouseEvent.cpp +++ b/Libraries/LibWeb/UIEvents/MouseEvent.cpp @@ -46,8 +46,8 @@ MouseEvent::MouseEvent(JS::Realm& realm, FlyString const& event_name, Bindings:: , m_movement_y(event_init.movement_y) , m_button(event_init.button) , m_buttons(event_init.buttons) - , m_related_target(event_init.related_target) { + set_related_target(event_init.related_target.ptr()); } MouseEvent::~MouseEvent() = default; @@ -58,12 +58,6 @@ void MouseEvent::initialize(JS::Realm& realm) Base::initialize(realm); } -void MouseEvent::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_related_target); -} - bool MouseEvent::get_modifier_state(String const& key_arg) const { if (key_arg == "Control") @@ -121,7 +115,7 @@ void MouseEvent::init_mouse_event(String const& type, bool bubbles, bool cancela m_alt_key = alt_key; m_meta_key = meta_key; m_button = button; - m_related_target = related_target; + set_related_target(related_target); } GC::Ref MouseEvent::create(JS::Realm& realm, FlyString const& event_name, Bindings::MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y) @@ -149,7 +143,7 @@ GC::Ref MouseEvent::clone() const init.movement_y = m_movement_y; init.button = m_button; init.buttons = m_buttons; - init.related_target = m_related_target; + init.related_target = related_target(); init.ctrl_key = m_ctrl_key; init.shift_key = m_shift_key; init.alt_key = m_alt_key; diff --git a/Libraries/LibWeb/UIEvents/MouseEvent.h b/Libraries/LibWeb/UIEvents/MouseEvent.h index 9a4e922337..f479148546 100644 --- a/Libraries/LibWeb/UIEvents/MouseEvent.h +++ b/Libraries/LibWeb/UIEvents/MouseEvent.h @@ -61,8 +61,6 @@ public: i16 button() const { return m_button; } u16 buttons() const { return m_buttons; } - GC::Ptr related_target() const { return m_related_target; } - bool get_modifier_state(String const& key_arg) const; virtual u32 which() const override { return m_button + 1; } @@ -78,7 +76,6 @@ protected: MouseEvent(JS::Realm&, FlyString const& event_name, Bindings::MouseEventInit const& event_init, double page_x, double page_y, double offset_x, double offset_y); virtual void initialize(JS::Realm&) override; - virtual void visit_edges(Cell::Visitor&) override; double m_screen_x { 0 }; double m_screen_y { 0 }; @@ -110,7 +107,6 @@ private: double m_movement_y { 0 }; i16 m_button { 0 }; u16 m_buttons { 0 }; - GC::Ptr m_related_target { nullptr }; }; } diff --git a/Tests/LibWeb/Text/expected/UIEvents/mouse-boundary-events-related-target.txt b/Tests/LibWeb/Text/expected/UIEvents/mouse-boundary-events-related-target.txt new file mode 100644 index 0000000000..f786bf7282 --- /dev/null +++ b/Tests/LibWeb/Text/expected/UIEvents/mouse-boundary-events-related-target.txt @@ -0,0 +1,6 @@ +pointerover: target=left, related=null +mouseover: target=left, related=null +pointerout: target=left, related=right +mouseout: target=left, related=right +pointerover: target=right, related=left +mouseover: target=right, related=left diff --git a/Tests/LibWeb/Text/input/UIEvents/mouse-boundary-events-related-target.html b/Tests/LibWeb/Text/input/UIEvents/mouse-boundary-events-related-target.html new file mode 100644 index 0000000000..b64960dee0 --- /dev/null +++ b/Tests/LibWeb/Text/input/UIEvents/mouse-boundary-events-related-target.html @@ -0,0 +1,28 @@ + + + +
+ +