summaryrefslogtreecommitdiff
path: root/dom
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2023-04-09 13:38:38 +0000
committerMoonchild <moonchild@palemoon.org>2023-04-09 13:38:38 +0000
commitb62bf0c4b7e70f3bfcc1915526e158712aef1211 (patch)
tree4ed5780064051bd9b8c0d4be5d1bebfcb65d0f44 /dom
parentc01fd8ec19ea7f170cf56241ce2ee803f4e2adc2 (diff)
parent78e4526d55adc049eacc6031fafd66fbe9a7e315 (diff)
downloaduxp-b62bf0c4b7e70f3bfcc1915526e158712aef1211.tar.gz
Merge pull request 'Implement window.event' (#2207) from FranklinDM/UXP-contrib:work_js-window-event into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/2207
Diffstat (limited to 'dom')
-rw-r--r--dom/base/FragmentOrElement.cpp4
-rw-r--r--dom/base/nsGlobalWindow.cpp13
-rw-r--r--dom/base/nsGlobalWindow.h1
-rw-r--r--dom/base/nsPIDOMWindow.h15
-rw-r--r--dom/events/EventDispatcher.cpp15
-rw-r--r--dom/events/EventDispatcher.h8
-rw-r--r--dom/events/EventListenerManager.cpp44
-rw-r--r--dom/events/EventListenerManager.h12
-rw-r--r--dom/webidl/Window.webidl1
9 files changed, 107 insertions, 6 deletions
diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
index 412031f98a..ccfe960cb7 100644
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -820,6 +820,10 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
aVisitor.mCanHandle = true;
aVisitor.mMayHaveListenerManager = HasListenerManager();
+ if (IsInShadowTree()) {
+ aVisitor.mItemInShadowTree = true;
+ }
+
// Don't propagate mouseover and mouseout events when mouse is moving
// inside chrome access only content.
bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index c6b35a9bf0..01023f3a2d 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -907,7 +907,8 @@ nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0
mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
- mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false)
+ mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
+ mEvent(nullptr)
{}
template<class T>
@@ -5244,6 +5245,16 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
}
void
+nsGlobalWindow::GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval)
+{
+ if (mEvent) {
+ Unused << nsContentUtils::WrapNative(aCx, mEvent, aRetval);
+ } else {
+ aRetval.setUndefined();
+ }
+}
+
+void
nsGlobalWindow::GetStatusOuter(nsAString& aStatus)
{
MOZ_RELEASE_ASSERT(IsOuterWindow());
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index e42835a0b2..e593890af0 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -845,6 +845,7 @@ public:
already_AddRefed<nsPIDOMWindowOuter> GetOpener() override;
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
mozilla::ErrorResult& aError);
+ void GetEvent(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h
index 21eb4cff7f..ffebf6570d 100644
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -194,6 +194,10 @@ protected:
// we have what it takes to do so.
void MaybeCreateDoc();
+ // The event dispatch code sets and unsets this while keeping
+ // the event object alive.
+ nsIDOMEvent* mEvent;
+
public:
inline bool IsLoadingOrRunningTimeout() const;
@@ -789,6 +793,17 @@ public:
return mInnerObjectsFreed;
}
+ // Sets the event for window.event. Does NOT take ownership, so
+ // the caller is responsible for clearing the event before the
+ // event gets deallocated. Pass nullptr to set window.event to
+ // undefined. Returns the previous value.
+ nsIDOMEvent* SetEvent(nsIDOMEvent* aEvent)
+ {
+ nsIDOMEvent* old = mEvent;
+ mEvent = aEvent;
+ return old;
+ }
+
/**
* Check whether this window is a secure context.
*/
diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp
index e2b5699241..001b458cf3 100644
--- a/dom/events/EventDispatcher.cpp
+++ b/dom/events/EventDispatcher.cpp
@@ -264,6 +264,16 @@ public:
return mFlags.mRootOfClosedTree;
}
+ void SetItemInShadowTree(bool aSet)
+ {
+ mFlags.mItemInShadowTree = aSet;
+ }
+
+ bool IsItemInShadowTree()
+ {
+ return mFlags.mItemInShadowTree;
+ }
+
void SetIsSlotInClosedTree(bool aSet)
{
mFlags.mIsSlotInClosedTree = aSet;
@@ -351,7 +361,8 @@ public:
mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
&aVisitor.mDOMEvent,
CurrentTarget(),
- &aVisitor.mEventStatus);
+ &aVisitor.mEventStatus,
+ IsItemInShadowTree());
NS_ASSERTION(aVisitor.mEvent->mCurrentTarget == nullptr,
"CurrentTarget should be null!");
}
@@ -384,6 +395,7 @@ private:
bool mWantsPreHandleEvent : 1;
bool mPreHandleEventOnly : 1;
bool mRootOfClosedTree : 1;
+ bool mItemInShadowTree : 1;
bool mIsSlotInClosedTree : 1;
bool mIsChromeHandler : 1;
private:
@@ -433,6 +445,7 @@ EventTargetChainItem::GetEventTargetParent(EventChainPreVisitor& aVisitor)
SetWantsPreHandleEvent(aVisitor.mWantsPreHandleEvent);
SetPreHandleEventOnly(aVisitor.mWantsPreHandleEvent && !aVisitor.mCanHandle);
SetRootOfClosedTree(aVisitor.mRootOfClosedTree);
+ SetItemInShadowTree(aVisitor.mItemInShadowTree);
SetRetargetedRelatedTarget(aVisitor.mRetargetedRelatedTarget);
mItemFlags = aVisitor.mItemFlags;
mItemData = aVisitor.mItemData;
diff --git a/dom/events/EventDispatcher.h b/dom/events/EventDispatcher.h
index 403c472c5c..9eaa124137 100644
--- a/dom/events/EventDispatcher.h
+++ b/dom/events/EventDispatcher.h
@@ -125,6 +125,7 @@ public:
, mMayHaveListenerManager(true)
, mWantsPreHandleEvent(false)
, mRootOfClosedTree(false)
+ , mItemInShadowTree(false)
, mParentIsSlotInClosedTree(false)
, mParentIsChromeHandler(false)
, mRelatedTargetRetargetedInCurrentScope(false)
@@ -147,6 +148,7 @@ public:
mMayHaveListenerManager = true;
mWantsPreHandleEvent = false;
mRootOfClosedTree = false;
+ mItemInShadowTree = false;
mParentIsSlotInClosedTree = false;
mParentIsChromeHandler = false;
// Note, we don't clear mRelatedTargetRetargetedInCurrentScope explicitly,
@@ -237,6 +239,12 @@ public:
bool mRootOfClosedTree;
/**
+ * If target is node and its root is a shadow root.
+ * https://dom.spec.whatwg.org/#event-path-item-in-shadow-tree
+ */
+ bool mItemInShadowTree;
+
+ /**
* True if mParentTarget is HTMLSlotElement in a closed shadow tree and the
* current target is assigned to that slot.
*/
diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp
index 221b464773..af268f24bb 100644
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -1120,6 +1120,38 @@ EventListenerManager::GetLegacyEventMessage(EventMessage aEventMessage) const
}
}
+already_AddRefed<nsPIDOMWindowInner>
+EventListenerManager::WindowFromListener(Listener* aListener,
+ bool aItemInShadowTree)
+{
+ nsCOMPtr<nsPIDOMWindowInner> innerWindow;
+ if (!aItemInShadowTree) {
+ if (aListener->mListener.HasWebIDLCallback()) {
+ CallbackObject* callback = aListener->mListener.GetWebIDLCallback();
+ nsGlobalWindow* win;
+ if (callback) {
+ // Find the real underlying callback.
+ JSObject* realCallback =
+ js::UncheckedUnwrap(callback->CallbackPreserveColor());
+ // Get the global for this callback.
+ win = mIsMainThreadELM ?
+ xpc::WindowGlobalOrNull(realCallback) :
+ nullptr;
+ }
+ if (win && win->IsInnerWindow()) {
+ innerWindow = win->AsInner(); // Can be nullptr
+ }
+ } else {
+ // Can't get the global from
+ // listener->mListener.GetXPCOMCallback().
+ // In most cases, it would be the same as for
+ // the target, so let's do that.
+ innerWindow = GetInnerWindowForTarget(); // Can be nullptr
+ }
+ }
+ return innerWindow.forget();
+}
+
/**
* Causes a check for event listeners and processing by them if they exist.
* @param an event listener
@@ -1130,7 +1162,8 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
WidgetEvent* aEvent,
nsIDOMEvent** aDOMEvent,
EventTarget* aCurrentTarget,
- nsEventStatus* aEventStatus)
+ nsEventStatus* aEventStatus,
+ bool aItemInShadowTree)
{
//Set the value of the internal PreventDefault flag properly based on aEventStatus
if (!aEvent->DefaultPrevented() &&
@@ -1222,9 +1255,18 @@ EventListenerManager::HandleEventInternal(nsPresContext* aPresContext,
listener = listenerHolder.ptr();
hasRemovedListener = true;
}
+ nsCOMPtr<nsPIDOMWindowInner> innerWindow =
+ WindowFromListener(listener, aItemInShadowTree);
+ nsIDOMEvent* oldWindowEvent = nullptr;
+ if (innerWindow) {
+ oldWindowEvent = innerWindow->SetEvent(*aDOMEvent);
+ }
if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
aEvent->mFlags.mExceptionWasRaised = true;
}
+ if (innerWindow) {
+ Unused << innerWindow->SetEvent(oldWindowEvent);
+ }
aEvent->mFlags.mInPassiveListener = false;
if (needsEndEventMarker) {
diff --git a/dom/events/EventListenerManager.h b/dom/events/EventListenerManager.h
index 51373317d4..decd305f5e 100644
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -350,7 +350,8 @@ public:
WidgetEvent* aEvent,
nsIDOMEvent** aDOMEvent,
dom::EventTarget* aCurrentTarget,
- nsEventStatus* aEventStatus)
+ nsEventStatus* aEventStatus,
+ bool aItemInShadowTree)
{
if (mListeners.IsEmpty() || aEvent->PropagationStopped()) {
return;
@@ -371,7 +372,7 @@ public:
return;
}
HandleEventInternal(aPresContext, aEvent, aDOMEvent, aCurrentTarget,
- aEventStatus);
+ aEventStatus, aItemInShadowTree);
}
/**
@@ -482,7 +483,8 @@ protected:
WidgetEvent* aEvent,
nsIDOMEvent** aDOMEvent,
dom::EventTarget* aCurrentTarget,
- nsEventStatus* aEventStatus);
+ nsEventStatus* aEventStatus,
+ bool aItemInShadowTree);
nsresult HandleEventSubType(Listener* aListener,
nsIDOMEvent* aDOMEvent,
@@ -573,6 +575,10 @@ public:
return typedHandler ? typedHandler->OnBeforeUnloadEventHandler() : nullptr;
}
+private:
+ already_AddRefed<nsPIDOMWindowInner> WindowFromListener(Listener* aListener,
+ bool aItemInShadowTree);
+
protected:
/**
* Helper method for implementing the various Get*EventHandler above. Will
diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl
index 1b98042473..6020f71dce 100644
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -51,6 +51,7 @@ typedef any Transferable;
[Throws] void stop();
[Throws, CrossOriginCallable, UnsafeInPrerendering] void focus();
[Throws, CrossOriginCallable] void blur();
+ [Replaceable, Pref="dom.window.event.enabled"] readonly attribute any event;
// other browsing contexts
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;