From a69e82b0d7d0617ba1e02257bb92491cafe9470a Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sat, 4 Mar 2023 02:23:31 +0800 Subject: Issue #2135 - Bug 1413102 (Follow-up): Ignore current target because of shadow DOM retargeting Based on https://bugzilla.mozilla.org/show_bug.cgi?id=1466581 --- dom/base/FragmentOrElement.cpp | 4 ++-- dom/events/EventDispatcher.cpp | 7 ++++++- dom/events/EventDispatcher.h | 11 ++++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index 7f287cb58d..412031f98a 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -991,7 +991,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) // Step 4. // "If target is relatedTarget and target is not event's // relatedTarget, then return true." - aVisitor.IgnoreCurrentTarget(); + aVisitor.IgnoreCurrentTargetBecauseOfShadowDOMRetargeting(); // Old code relies on mTarget to point to the first element which // was not added to the event target chain because of mCanHandle // being false, but in Shadow DOM case mTarget really should @@ -1030,7 +1030,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) // Step 11.5 // "Otherwise, if parent and relatedTarget are identical, then set // parent to null." - aVisitor.IgnoreCurrentTarget(); + aVisitor.IgnoreCurrentTargetBecauseOfShadowDOMRetargeting(); // Old code relies on mTarget to point to the first element which // was not added to the event target chain because of mCanHandle // being false, but in Shadow DOM case mTarget really should diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index 9a48ca2a90..e2b5699241 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -872,6 +872,7 @@ EventDispatcher::Dispatch(nsISupports* aTarget, preVisitor.mTargetInKnownToBeHandledScope = preVisitor.mEvent->mTarget; topEtci = parentEtci; } else { + bool ignoreBecauseOfShadowDOM = preVisitor.mIgnoreBecauseOfShadowDOM; nsCOMPtr disabledTarget = do_QueryInterface(parentTarget); parentEtci = MayRetargetToChromeIfCanNotHandleEvent(chain, preVisitor, @@ -882,7 +883,11 @@ EventDispatcher::Dispatch(nsISupports* aTarget, preVisitor.mTargetInKnownToBeHandledScope = preVisitor.mEvent->mTarget; EventTargetChainItem* item = EventTargetChainItem::GetFirstCanHandleEventTarget(chain); - item->SetNewTarget(parentTarget); + if (!ignoreBecauseOfShadowDOM) { + // If we ignored the target because of Shadow DOM retargeting, we + // shouldn't treat the target to be in the event path at all. + item->SetNewTarget(parentTarget); + } topEtci = parentEtci; continue; } diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h index 529240d0ac..403c472c5c 100644 --- a/dom/events/EventDispatcher.h +++ b/dom/events/EventDispatcher.h @@ -128,6 +128,7 @@ public: , mParentIsSlotInClosedTree(false) , mParentIsChromeHandler(false) , mRelatedTargetRetargetedInCurrentScope(false) + , mIgnoreBecauseOfShadowDOM(false) , mParentTarget(nullptr) , mEventTargetAtParent(nullptr) , mRetargetedRelatedTarget(nullptr) @@ -151,6 +152,7 @@ public: // Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly, // since it is used during event path creation to indicate whether // relatedTarget may need to be retargeted. + mIgnoreBecauseOfShadowDOM = false; mParentTarget = nullptr; mEventTargetAtParent = nullptr; mRetargetedRelatedTarget = nullptr; @@ -169,9 +171,10 @@ public: } } - void IgnoreCurrentTarget() + void IgnoreCurrentTargetBecauseOfShadowDOMRetargeting() { mCanHandle = false; + mIgnoreBecauseOfShadowDOM = true; SetParentTarget(nullptr, false); mEventTargetAtParent = nullptr; } @@ -251,6 +254,12 @@ public: */ bool mRelatedTargetRetargetedInCurrentScope; + /** + * True if Shadow DOM relatedTarget retargeting causes the current item + * to not show up in the event path. + */ + bool mIgnoreBecauseOfShadowDOM; + private: /** * Parent item in the event target chain. -- cgit v1.2.3