diff options
author | Matt A. Tobin <email@mattatobin.com> | 2020-04-17 07:30:43 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2020-04-17 07:30:43 -0400 |
commit | 7e506bd98dab604062bfe12a44c096eb287721bf (patch) | |
tree | ebea23264b1fa0f9c23935b253c23bdc0b41c25d | |
parent | 010f37f47b9c15935a6113cd82e43f0673122016 (diff) | |
download | UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar.gz UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar.lz UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar.xz UXP-7e506bd98dab604062bfe12a44c096eb287721bf.zip |
Bug 1412775 - Implement Event.composedPath
Tag #1375
24 files changed, 194 insertions, 131 deletions
diff --git a/dom/archivereader/ArchiveRequest.cpp b/dom/archivereader/ArchiveRequest.cpp index c4b19f56b..832dec3fa 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 ecb18798f..5b2fabd8d 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 308f57cf7..e7f7ae93c 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<nsIContent> content(do_QueryInterface(aVisitor.mEvent->mTarget)); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 459ad6bdd..d2763eddd 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 802b44f38..69643762c 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 547bb8d36..9885b41a8 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 b629ab86f..710ecd88f 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<nsISupports *>(mWindow); - aVisitor.mParentTarget = mParent; + aVisitor.SetParentTarget(mParent, false); return NS_OK; } diff --git a/dom/events/DOMEventTargetHelper.cpp b/dom/events/DOMEventTargetHelper.cpp index ee03463ef..90ee61059 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 280e40ad5..def298228 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<RefPtr<EventTarget>>& aPath) +{ + EventDispatcher::GetComposedPathFor(mEvent, aPath); +} + NS_IMETHODIMP Event::GetCurrentTarget(nsIDOMEventTarget** aCurrentTarget) { diff --git a/dom/events/Event.h b/dom/events/Event.h index 0817aa809..4f1fcc827 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<RefPtr<EventTarget>>& aPath); + uint16_t EventPhase() const; // xpidl implementation diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index 740e611e4..1094c08c2 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<RefPtr<EventTarget>>& aPath) +{ + nsTArray<EventTargetChainItem>* path = aEvent->mPath; + if (!path || path->IsEmpty() || !aEvent->mCurrentTarget) { + return; + } + + EventTarget* currentTarget = + aEvent->mCurrentTarget->GetTargetForEventTargetChain(); + if (!currentTarget) { + return; + } + + AutoTArray<EventTarget*, 128> 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 618c863d5..8a34e6bf7 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 @@ -195,10 +214,29 @@ 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<RefPtr<dom::EventTarget>>& aPath); + /** * Called at shutting down. */ diff --git a/dom/indexedDB/IDBFileHandle.cpp b/dom/indexedDB/IDBFileHandle.cpp index 55dd22ce9..93e163c11 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 7d93f24de..1401f7c76 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 b74725954..5ce077e33 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 ec27c51d8..0a10e2ca0 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 a5d7da7d4..8a8e71c43 100644 --- a/dom/webidl/Event.webidl +++ b/dom/webidl/Event.webidl @@ -22,6 +22,8 @@ interface Event { [Pure] readonly attribute EventTarget? currentTarget; + sequence<EventTarget> 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 750dc9237..71c644405 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 af050d9f8..2ae03e0b1 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 c58edca31..9760e42ea 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 afe0ce8b0..000000000 --- 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 ecd6e3094..0566bf4f3 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 6386a51c5..000000000 --- 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 960cb67c6..4e9e0e6ce 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<dom::EventTarget> mCurrentTarget; nsCOMPtr<dom::EventTarget> mOriginalTarget; + nsTArray<EventTargetChainItem>* mPath; + dom::EventTarget* GetDOMEventTarget() const; dom::EventTarget* GetCurrentDOMEventTarget() const; dom::EventTarget* GetOriginalDOMEventTarget() const; |