From 2ee3ce62fc282735962d33c827e9f1205cf627ec Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 17 Apr 2020 07:30:43 -0400 Subject: [PATCH] Bug 1412775 - Implement Event.composedPath Tag #1375 --- dom/archivereader/ArchiveRequest.cpp | 2 +- dom/base/FragmentOrElement.cpp | 17 ++- dom/base/ShadowRoot.cpp | 5 +- dom/base/nsDocument.cpp | 4 +- dom/base/nsGlobalWindow.cpp | 2 +- dom/base/nsInProcessTabChildGlobal.cpp | 8 +- dom/base/nsWindowRoot.cpp | 2 +- dom/events/DOMEventTargetHelper.cpp | 2 +- dom/events/Event.cpp | 7 ++ dom/events/Event.h | 2 + dom/events/EventDispatcher.cpp | 107 +++++++++++++++++- dom/events/EventDispatcher.h | 41 +++++++ dom/indexedDB/IDBFileHandle.cpp | 2 +- dom/indexedDB/IDBFileRequest.cpp | 2 +- dom/indexedDB/IDBRequest.cpp | 2 +- dom/indexedDB/IDBTransaction.cpp | 2 +- dom/webidl/Event.webidl | 2 + dom/workers/SharedWorker.cpp | 2 +- dom/xul/nsXULElement.cpp | 2 +- .../Extensions-to-Event-Interface.html.ini | 8 -- ...composed-path-with-related-target.html.ini | 48 -------- .../shadow-dom/event-composed-path.html.ini | 27 ----- .../meta/shadow-dom/event-composed.html.ini | 23 ---- widget/BasicEvents.h | 6 + 24 files changed, 194 insertions(+), 131 deletions(-) delete mode 100644 testing/web-platform/meta/shadow-dom/event-composed-path-with-related-target.html.ini delete mode 100644 testing/web-platform/meta/shadow-dom/event-composed.html.ini diff --git a/dom/archivereader/ArchiveRequest.cpp b/dom/archivereader/ArchiveRequest.cpp index c4b19f56bc..832dec3fac 100644 --- a/dom/archivereader/ArchiveRequest.cpp +++ b/dom/archivereader/ArchiveRequest.cpp @@ -72,7 +72,7 @@ nsresult ArchiveRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = true; - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp index ecb18798f8..5b2fabd8d2 100644 --- a/dom/base/FragmentOrElement.cpp +++ b/dom/base/FragmentOrElement.cpp @@ -813,6 +813,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) // Don't propagate mouseover and mouseout events when mouse is moving // inside chrome access only content. bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree(); + aVisitor.mRootOfClosedTree = isAnonForEvents; if ((aVisitor.mEvent->mMessage == eMouseOver || aVisitor.mEvent->mMessage == eMouseOut || aVisitor.mEvent->mMessage == ePointerOver || @@ -834,7 +835,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) nsIContent* adjustedTarget = Event::GetShadowRelatedTarget(this, relatedTarget); if (this == adjustedTarget) { - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); aVisitor.mCanHandle = false; return NS_OK; } @@ -891,7 +892,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) originalTarget->FindFirstNonChromeOnlyAccessContent()) ? "" : "Wrong event propagation!?!\n"); #endif - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); // Event should not propagate to non-anon content. aVisitor.mCanHandle = isAnonForEvents; return NS_OK; @@ -943,11 +944,17 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) if (!aVisitor.mEvent->mFlags.mComposedInNativeAnonymousContent && IsRootOfNativeAnonymousSubtree() && OwnerDoc() && OwnerDoc()->GetWindow()) { - aVisitor.mParentTarget = OwnerDoc()->GetWindow()->GetParentTarget(); + aVisitor.SetParentTarget(OwnerDoc()->GetWindow()->GetParentTarget(), true); } else if (parent) { - aVisitor.mParentTarget = parent; + aVisitor.SetParentTarget(parent, false); + if (slot) { + ShadowRoot* root = slot->GetContainingShadow(); + if (root && root->IsClosed()) { + aVisitor.mParentIsSlotInClosedTree = true; + } + } } else { - aVisitor.mParentTarget = GetComposedDoc(); + aVisitor.SetParentTarget(GetComposedDoc(), false); } return NS_OK; } diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp index 308f57cf74..e7f7ae93c4 100644 --- a/dom/base/ShadowRoot.cpp +++ b/dom/base/ShadowRoot.cpp @@ -309,6 +309,7 @@ nsresult ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = true; + aVisitor.mRootOfClosedTree = IsClosed(); // https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6 if (!aVisitor.mEvent->mFlags.mComposed) { @@ -323,13 +324,13 @@ ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad ? win->GetParentTarget() : nullptr; - aVisitor.mParentTarget = parentTarget; + aVisitor.SetParentTarget(parentTarget, true); return NS_OK; } } nsIContent* shadowHost = GetHost(); - aVisitor.mParentTarget = shadowHost; + aVisitor.SetParentTarget(shadowHost, false); if (aVisitor.mOriginalTargetIsInAnon) { nsCOMPtr content(do_QueryInterface(aVisitor.mEvent->mTarget)); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 459ad6bddb..d2763edddf 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -7531,8 +7531,8 @@ nsDocument::GetEventTargetParent(EventChainPreVisitor& aVisitor) // Load events must not propagate to |window| object, see bug 335251. if (aVisitor.mEvent->mMessage != eLoad) { nsGlobalWindow* window = nsGlobalWindow::Cast(GetWindow()); - aVisitor.mParentTarget = - window ? window->GetTargetForEventTargetChain() : nullptr; + aVisitor.SetParentTarget( + window ? window->GetTargetForEventTargetChain() : nullptr, false); } return NS_OK; } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 802b44f381..69643762c5 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -3608,7 +3608,7 @@ nsGlobalWindow::GetEventTargetParent(EventChainPreVisitor& aVisitor) } } - aVisitor.mParentTarget = GetParentTarget(); + aVisitor.SetParentTarget(GetParentTarget(), true); // Handle 'active' event. if (!mIdleObservers.IsEmpty() && diff --git a/dom/base/nsInProcessTabChildGlobal.cpp b/dom/base/nsInProcessTabChildGlobal.cpp index 547bb8d36b..9885b41a83 100644 --- a/dom/base/nsInProcessTabChildGlobal.cpp +++ b/dom/base/nsInProcessTabChildGlobal.cpp @@ -270,7 +270,7 @@ nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor) #endif if (mPreventEventsEscaping) { - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } @@ -278,11 +278,13 @@ nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor) (!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) { if (mOwner) { if (nsPIDOMWindowInner* innerWindow = mOwner->OwnerDoc()->GetInnerWindow()) { - aVisitor.mParentTarget = innerWindow->GetParentTarget(); + // 'this' is already a "chrome handler", so we consider window's + // parent target to be part of that same part of the event path. + aVisitor.SetParentTarget(innerWindow->GetParentTarget(), false); } } } else { - aVisitor.mParentTarget = mOwner; + aVisitor.SetParentTarget(mOwner, false); } return NS_OK; diff --git a/dom/base/nsWindowRoot.cpp b/dom/base/nsWindowRoot.cpp index b629ab86f2..710ecd88f3 100644 --- a/dom/base/nsWindowRoot.cpp +++ b/dom/base/nsWindowRoot.cpp @@ -186,7 +186,7 @@ nsWindowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor) aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119 // To keep mWindow alive aVisitor.mItemData = static_cast(mWindow); - aVisitor.mParentTarget = mParent; + aVisitor.SetParentTarget(mParent, false); return NS_OK; } diff --git a/dom/events/DOMEventTargetHelper.cpp b/dom/events/DOMEventTargetHelper.cpp index ee03463ef4..90ee610594 100644 --- a/dom/events/DOMEventTargetHelper.cpp +++ b/dom/events/DOMEventTargetHelper.cpp @@ -331,7 +331,7 @@ nsresult DOMEventTargetHelper::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = true; - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } diff --git a/dom/events/Event.cpp b/dom/events/Event.cpp index 280e40ad57..def298228d 100755 --- a/dom/events/Event.cpp +++ b/dom/events/Event.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/ShadowRoot.h" #include "mozilla/ContentEvents.h" #include "mozilla/DOMEventTargetHelper.h" +#include "mozilla/EventDispatcher.h" #include "mozilla/EventStateManager.h" #include "mozilla/InternalMutationEvent.h" #include "mozilla/dom/Performance.h" @@ -298,6 +299,12 @@ Event::GetCurrentTarget() const return mEvent->GetCurrentDOMEventTarget(); } +void +Event::ComposedPath(nsTArray>& aPath) +{ + EventDispatcher::GetComposedPathFor(mEvent, aPath); +} + NS_IMETHODIMP Event::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) { diff --git a/dom/events/Event.h b/dom/events/Event.h index 0817aa809e..4f1fcc8270 100755 --- a/dom/events/Event.h +++ b/dom/events/Event.h @@ -157,6 +157,8 @@ public: EventTarget* GetTarget() const; EventTarget* GetCurrentTarget() const; + void ComposedPath(nsTArray>& aPath); + uint16_t EventPhase() const; // xpidl implementation diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index 740e611e49..1094c08c20 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -246,6 +246,36 @@ public: return mFlags.mPreHandleEventOnly; } + void SetRootOfClosedTree(bool aSet) + { + mFlags.mRootOfClosedTree = aSet; + } + + bool IsRootOfClosedTree() + { + return mFlags.mRootOfClosedTree; + } + + void SetIsSlotInClosedTree(bool aSet) + { + mFlags.mIsSlotInClosedTree = aSet; + } + + bool IsSlotInClosedTree() + { + return mFlags.mIsSlotInClosedTree; + } + + void SetIsChromeHandler(bool aSet) + { + mFlags.mIsChromeHandler = aSet; + } + + bool IsChromeHandler() + { + return mFlags.mIsChromeHandler; + } + void SetMayHaveListenerManager(bool aMayHave) { mFlags.mMayHaveManager = aMayHave; @@ -344,6 +374,9 @@ private: bool mIsChromeContent : 1; bool mWantsPreHandleEvent : 1; bool mPreHandleEventOnly : 1; + bool mRootOfClosedTree : 1; + bool mIsSlotInClosedTree : 1; + bool mIsChromeHandler : 1; private: typedef uint32_t RawFlags; void SetRawFlags(RawFlags aRawFlags) @@ -390,6 +423,7 @@ EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor) SetMayHaveListenerManager(aVisitor.mMayHaveListenerManager); SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent); SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle); + SetRootOfClosedTree(aVisitor.mRootOfClosedTree); mItemFlags = aVisitor.mItemFlags; mItemData = aVisitor.mItemData; } @@ -761,16 +795,19 @@ EventDispatcher::Dispatch(nsISupports* aTarget, targetEtci->SetNewTarget(t); EventTargetChainItem* topEtci = targetEtci; targetEtci = nullptr; - while (preVisitor.mParentTarget) { - EventTarget* parentTarget = preVisitor.mParentTarget; + while (preVisitor.GetParentTarget()) { + EventTarget* parentTarget = preVisitor.GetParentTarget(); EventTargetChainItem* parentEtci = - EventTargetChainItem::Create(chain, preVisitor.mParentTarget, topEtci); + EventTargetChainItem::Create(chain, parentTarget, topEtci); if (!parentEtci->IsValid()) { EventTargetChainItem::DestroyLast(chain, parentEtci); rv = NS_ERROR_FAILURE; break; } + parentEtci->SetIsSlotInClosedTree(preVisitor.mParentIsSlotInClosedTree); + parentEtci->SetIsChromeHandler(preVisitor.mParentIsChromeHandler); + // Item needs event retargetting. if (preVisitor.mEventTargetAtParent) { // Need to set the target of the event @@ -814,9 +851,13 @@ EventDispatcher::Dispatch(nsISupports* aTarget, } // Handle the chain. EventChainPostVisitor postVisitor(preVisitor); + MOZ_RELEASE_ASSERT(!aEvent->mPath); + aEvent->mPath = &chain; EventTargetChainItem::HandleEventTargetChain(chain, postVisitor, aCallback, cd); + aEvent->mPath = nullptr; + preVisitor.mEventStatus = postVisitor.mEventStatus; // If the DOM event was created during event flow. if (!preVisitor.mDOMEvent && postVisitor.mDOMEvent) { @@ -1128,4 +1169,64 @@ EventDispatcher::CreateEvent(EventTarget* aOwner, return nullptr; } +// static +void +EventDispatcher::GetComposedPathFor(WidgetEvent* aEvent, + nsTArray>& aPath) +{ + nsTArray* path = aEvent->mPath; + if (!path || path->IsEmpty() || !aEvent->mCurrentTarget) { + return; + } + + EventTarget* currentTarget = + aEvent->mCurrentTarget->GetTargetForEventTargetChain(); + if (!currentTarget) { + return; + } + + AutoTArray reversedComposedPath; + bool hasSeenCurrentTarget = false; + uint32_t hiddenSubtreeLevel = 0; + for (uint32_t i = path->Length(); i; ) { + --i; + + EventTargetChainItem& item = path->ElementAt(i); + if (item.PreHandleEventOnly()) { + continue; + } + + if (!hasSeenCurrentTarget && currentTarget == item.CurrentTarget()) { + hasSeenCurrentTarget = true; + } else if (hasSeenCurrentTarget && item.IsRootOfClosedTree()) { + ++hiddenSubtreeLevel; + } + + if (hiddenSubtreeLevel == 0) { + reversedComposedPath.AppendElement(item.CurrentTarget()); + } + + if (item.IsSlotInClosedTree() && hiddenSubtreeLevel > 0) { + --hiddenSubtreeLevel; + } + + if (item.IsChromeHandler()) { + if (hasSeenCurrentTarget) { + // The current behavior is to include only EventTargets from + // either chrome side of event path or content side, not from both. + break; + } + + // Need to start all over to collect the composed path on content side. + reversedComposedPath.Clear(); + } + } + + aPath.SetCapacity(reversedComposedPath.Length()); + for (uint32_t i = reversedComposedPath.Length(); i; ) { + --i; + aPath.AppendElement(reversedComposedPath[i]->GetTargetForDOMEvent()); + } +} + } // namespace mozilla diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h index 618c863d5c..8a34e6bf78 100644 --- a/dom/events/EventDispatcher.h +++ b/dom/events/EventDispatcher.h @@ -124,6 +124,9 @@ public: , mWantsWillHandleEvent(false) , mMayHaveListenerManager(true) , mWantsPreHandleEvent(false) + , mRootOfClosedTree(false) + , mParentIsSlotInClosedTree(false) + , mParentIsChromeHandler(false) , mParentTarget(nullptr) , mEventTargetAtParent(nullptr) { @@ -139,10 +142,26 @@ public: mWantsWillHandleEvent = false; mMayHaveListenerManager = true; mWantsPreHandleEvent = false; + mRootOfClosedTree = false; + mParentIsSlotInClosedTree = false; + mParentIsChromeHandler = false; mParentTarget = nullptr; mEventTargetAtParent = nullptr; } + dom::EventTarget* GetParentTarget() + { + return mParentTarget; + } + + void SetParentTarget(dom::EventTarget* aParentTarget, bool aIsChromeHandler) + { + mParentTarget = aParentTarget; + if (mParentTarget) { + mParentIsChromeHandler = aIsChromeHandler; + } + } + /** * Member that must be set in GetEventTargetParent by event targets. If set to * false, indicates that this event target will not be handling the event and @@ -194,11 +213,30 @@ public: */ bool mWantsPreHandleEvent; + /** + * True if the current target is either closed ShadowRoot or root of + * chrome only access tree (for example native anonymous content). + */ + bool mRootOfClosedTree; + + /** + * True if mParentTarget is HTMLSlotElement in a closed shadow tree and the + * current target is assigned to that slot. + */ + bool mParentIsSlotInClosedTree; + + /** + * True if mParentTarget is a chrome handler in the event path. + */ + bool mParentIsChromeHandler; + +private: /** * Parent item in the event target chain. */ dom::EventTarget* mParentTarget; +public: /** * If the event needs to be retargeted, this is the event target, * which should be used when the event is handled at mParentTarget. @@ -281,6 +319,9 @@ public: WidgetEvent* aEvent, const nsAString& aEventType); + static void GetComposedPathFor(WidgetEvent* aEvent, + nsTArray>& aPath); + /** * Called at shutting down. */ diff --git a/dom/indexedDB/IDBFileHandle.cpp b/dom/indexedDB/IDBFileHandle.cpp index 55dd22ce93..93e163c116 100644 --- a/dom/indexedDB/IDBFileHandle.cpp +++ b/dom/indexedDB/IDBFileHandle.cpp @@ -132,7 +132,7 @@ IDBFileHandle::GetEventTargetParent(EventChainPreVisitor& aVisitor) AssertIsOnOwningThread(); aVisitor.mCanHandle = true; - aVisitor.mParentTarget = mMutableFile; + aVisitor.SetParentTarget(mMutableFile, false); return NS_OK; } diff --git a/dom/indexedDB/IDBFileRequest.cpp b/dom/indexedDB/IDBFileRequest.cpp index 7d93f24dee..1401f7c76c 100644 --- a/dom/indexedDB/IDBFileRequest.cpp +++ b/dom/indexedDB/IDBFileRequest.cpp @@ -69,7 +69,7 @@ IDBFileRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor) AssertIsOnOwningThread(); aVisitor.mCanHandle = true; - aVisitor.mParentTarget = mFileHandle; + aVisitor.SetParentTarget(mFileHandle, false); return NS_OK; } diff --git a/dom/indexedDB/IDBRequest.cpp b/dom/indexedDB/IDBRequest.cpp index b747259546..5ce077e33f 100644 --- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -454,7 +454,7 @@ IDBRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor) AssertIsOnOwningThread(); aVisitor.mCanHandle = true; - aVisitor.mParentTarget = mTransaction; + aVisitor.SetParentTarget(mTransaction, false); return NS_OK; } diff --git a/dom/indexedDB/IDBTransaction.cpp b/dom/indexedDB/IDBTransaction.cpp index ec27c51d89..0a10e2ca0e 100644 --- a/dom/indexedDB/IDBTransaction.cpp +++ b/dom/indexedDB/IDBTransaction.cpp @@ -1001,7 +1001,7 @@ IDBTransaction::GetEventTargetParent(EventChainPreVisitor& aVisitor) AssertIsOnOwningThread(); aVisitor.mCanHandle = true; - aVisitor.mParentTarget = mDatabase; + aVisitor.SetParentTarget(mDatabase, false); return NS_OK; } diff --git a/dom/webidl/Event.webidl b/dom/webidl/Event.webidl index a5d7da7d43..8a8e71c43b 100644 --- a/dom/webidl/Event.webidl +++ b/dom/webidl/Event.webidl @@ -22,6 +22,8 @@ interface Event { [Pure] readonly attribute EventTarget? currentTarget; + sequence composedPath(); + const unsigned short NONE = 0; const unsigned short CAPTURING_PHASE = 1; const unsigned short AT_TARGET = 2; diff --git a/dom/workers/SharedWorker.cpp b/dom/workers/SharedWorker.cpp index 750dc9237f..71c644405c 100644 --- a/dom/workers/SharedWorker.cpp +++ b/dom/workers/SharedWorker.cpp @@ -196,7 +196,7 @@ SharedWorker::GetEventTargetParent(EventChainPreVisitor& aVisitor) QueueEvent(event); aVisitor.mCanHandle = false; - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } diff --git a/dom/xul/nsXULElement.cpp b/dom/xul/nsXULElement.cpp index af050d9f81..2ae03e0b17 100644 --- a/dom/xul/nsXULElement.cpp +++ b/dom/xul/nsXULElement.cpp @@ -1303,7 +1303,7 @@ nsXULElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) if (IsEventStoppedFromAnonymousScrollbar(aVisitor.mEvent->mMessage)) { // Don't propagate these events from native anonymous scrollbar. aVisitor.mCanHandle = true; - aVisitor.mParentTarget = nullptr; + aVisitor.SetParentTarget(nullptr, false); return NS_OK; } if (aVisitor.mEvent->mMessage == eXULCommand && diff --git a/testing/web-platform/meta/shadow-dom/Extensions-to-Event-Interface.html.ini b/testing/web-platform/meta/shadow-dom/Extensions-to-Event-Interface.html.ini index c58edca31d..9760e42eae 100644 --- a/testing/web-platform/meta/shadow-dom/Extensions-to-Event-Interface.html.ini +++ b/testing/web-platform/meta/shadow-dom/Extensions-to-Event-Interface.html.ini @@ -1,13 +1,5 @@ [Extensions-to-Event-Interface.html] type: testharness - [composedPath() must exist on Event] - expected: FAIL - - [composedPath() must return an empty array when the event has not been dispatched] - expected: FAIL - - [composedPath() must return an empty array when the event is no longer dispatched] - expected: FAIL [The event must propagate out of open mode shadow boundaries when the composed flag is set] expected: FAIL diff --git a/testing/web-platform/meta/shadow-dom/event-composed-path-with-related-target.html.ini b/testing/web-platform/meta/shadow-dom/event-composed-path-with-related-target.html.ini deleted file mode 100644 index afe0ce8b0c..0000000000 --- a/testing/web-platform/meta/shadow-dom/event-composed-path-with-related-target.html.ini +++ /dev/null @@ -1,48 +0,0 @@ -[event-composed-path-with-related-target.html] - type: testharness - expected: ERROR - [Event path for an event with a relatedTarget. relatedTarget != target.] - expected: FAIL - - [Event path for an event with a relatedTarget. Event shoul be dispatched if 1) target and relatedTarget are same, and 2) they are not in a shadow tree.] - expected: FAIL - - [Event path for an event with a relatedTarget. Event should stop at the shadow root] - expected: FAIL - - [Event path for an event with a relatedTarget. Event should not be dispatched if 1) target and relatedTarget are same, and 2) both are in a shadow tree.] - expected: FAIL - - [Event path for an event with a relatedTarget. target and relaterTarget do not share any shadow-including ancestor. target is in a shadow tree.] - expected: FAIL - - [Event path for an event with a relatedTarget. target and relaterTarget do not share any shadow-including ancestor. target is not in a shadow tree] - expected: FAIL - - [Event path for an event with a relatedTarget. target and relaterTarget share the same shadow-including ancestor. Both are in shadow trees.] - expected: FAIL - - [Event path for an event with a relatedTarget. relaterTarget is a shadow-including ancestor of target.] - expected: FAIL - - [Event path for an event with a relatedTarget. target is a shadow-including ancestor of relatedTarget.] - expected: FAIL - - [Event path for an event with a relatedTarget. target is assigned to a slot.] - expected: FAIL - - [Event path for an event with a relatedTarget. relatedTarget is assigned to a slot.] - expected: FAIL - - [Event path for an event with a relatedTarget. Event should be dispatched at every slots.] - expected: FAIL - - [Event path for an event with a relatedTarget. Event should be dispatched at every slots. relatedTarget should be correctly retargeted.] - expected: FAIL - - [Event path for an event with a relatedTarget. Event should be dispatched even when target and relatedTarget are same.] - expected: FAIL - - [Event path for an event with a relatedTarget which is identical to target. Event should be dispatched and should stop at the shadow root.] - expected: FAIL - diff --git a/testing/web-platform/meta/shadow-dom/event-composed-path.html.ini b/testing/web-platform/meta/shadow-dom/event-composed-path.html.ini index ecd6e30944..0566bf4f31 100644 --- a/testing/web-platform/meta/shadow-dom/event-composed-path.html.ini +++ b/testing/web-platform/meta/shadow-dom/event-composed-path.html.ini @@ -1,36 +1,9 @@ [event-composed-path.html] type: testharness - expected: ERROR - [Event Path without ShadowRoots.] - expected: FAIL - - [Event Path with an open ShadowRoot.] - expected: FAIL - - [Event Path with a closed ShadowRoot.] - expected: FAIL - - [Event Path with nested ShadowRoots: open > open.] - expected: FAIL - - [Event Path with nested ShadowRoots: open > closed.] - expected: FAIL - - [Event Path with nested ShadowRoots: closed > open.] - expected: FAIL - - [Event Path with nested ShadowRoots: closed > closed.] - expected: FAIL - - [Event Path with a slot in an open Shadow Root.] - expected: FAIL [Event Path with a slot in a closed Shadow Root.] expected: FAIL - [Event Path with slots in nested ShadowRoots: open > open.] - expected: FAIL - [Event Path with slots in nested ShadowRoots: closed > closed.] expected: FAIL diff --git a/testing/web-platform/meta/shadow-dom/event-composed.html.ini b/testing/web-platform/meta/shadow-dom/event-composed.html.ini deleted file mode 100644 index 6386a51c59..0000000000 --- a/testing/web-platform/meta/shadow-dom/event-composed.html.ini +++ /dev/null @@ -1,23 +0,0 @@ -[event-composed.html] - type: testharness - [An event should be scoped by default] - expected: FAIL - - [An event should not be scoped if composed is specified] - expected: FAIL - - [A synthetic MouseEvent should be scoped by default] - expected: FAIL - - [A synthetic MouseEvent with composed=true should not be scoped] - expected: FAIL - - [A synthetic FocusEvent should be scoped by default] - expected: FAIL - - [A synthetic FocusEvent with composed=true should not be scoped] - expected: FAIL - - [A UA click event should not be scoped] - expected: FAIL - diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index 960cb67c68..4e9e0e6cea 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -25,6 +25,8 @@ struct ParamTraits; namespace mozilla { +class EventTargetChainItem; + /****************************************************************************** * mozilla::BaseEventFlags * @@ -350,6 +352,7 @@ protected: , mRefPoint(0, 0) , mLastRefPoint(0, 0) , mSpecifiedEventType(nullptr) + , mPath(nullptr) { MOZ_COUNT_CTOR(WidgetEvent); mFlags.Clear(); @@ -361,6 +364,7 @@ protected: WidgetEvent() : WidgetEventTime() + , mPath(nullptr) { MOZ_COUNT_CTOR(WidgetEvent); } @@ -419,6 +423,8 @@ public: nsCOMPtr mCurrentTarget; nsCOMPtr mOriginalTarget; + nsTArray* mPath; + dom::EventTarget* GetDOMEventTarget() const; dom::EventTarget* GetCurrentDOMEventTarget() const; dom::EventTarget* GetOriginalDOMEventTarget() const;