summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2020-04-17 07:30:43 -0400
committerMatt A. Tobin <email@mattatobin.com>2020-04-17 07:30:43 -0400
commit7e506bd98dab604062bfe12a44c096eb287721bf (patch)
treeebea23264b1fa0f9c23935b253c23bdc0b41c25d
parent010f37f47b9c15935a6113cd82e43f0673122016 (diff)
downloadUXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar
UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar.gz
UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar.lz
UXP-7e506bd98dab604062bfe12a44c096eb287721bf.tar.xz
UXP-7e506bd98dab604062bfe12a44c096eb287721bf.zip
Bug 1412775 - Implement Event.composedPath
Tag #1375
-rw-r--r--dom/archivereader/ArchiveRequest.cpp2
-rw-r--r--dom/base/FragmentOrElement.cpp17
-rw-r--r--dom/base/ShadowRoot.cpp5
-rw-r--r--dom/base/nsDocument.cpp4
-rw-r--r--dom/base/nsGlobalWindow.cpp2
-rw-r--r--dom/base/nsInProcessTabChildGlobal.cpp8
-rw-r--r--dom/base/nsWindowRoot.cpp2
-rw-r--r--dom/events/DOMEventTargetHelper.cpp2
-rwxr-xr-xdom/events/Event.cpp7
-rwxr-xr-xdom/events/Event.h2
-rw-r--r--dom/events/EventDispatcher.cpp107
-rw-r--r--dom/events/EventDispatcher.h41
-rw-r--r--dom/indexedDB/IDBFileHandle.cpp2
-rw-r--r--dom/indexedDB/IDBFileRequest.cpp2
-rw-r--r--dom/indexedDB/IDBRequest.cpp2
-rw-r--r--dom/indexedDB/IDBTransaction.cpp2
-rw-r--r--dom/webidl/Event.webidl2
-rw-r--r--dom/workers/SharedWorker.cpp2
-rw-r--r--dom/xul/nsXULElement.cpp2
-rw-r--r--testing/web-platform/meta/shadow-dom/Extensions-to-Event-Interface.html.ini8
-rw-r--r--testing/web-platform/meta/shadow-dom/event-composed-path-with-related-target.html.ini48
-rw-r--r--testing/web-platform/meta/shadow-dom/event-composed-path.html.ini27
-rw-r--r--testing/web-platform/meta/shadow-dom/event-composed.html.ini23
-rw-r--r--widget/BasicEvents.h6
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;