diff options
author | Moonchild <moonchild@palemoon.org> | 2023-04-09 13:38:38 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2023-04-09 13:38:38 +0000 |
commit | b62bf0c4b7e70f3bfcc1915526e158712aef1211 (patch) | |
tree | 4ed5780064051bd9b8c0d4be5d1bebfcb65d0f44 /dom | |
parent | c01fd8ec19ea7f170cf56241ce2ee803f4e2adc2 (diff) | |
parent | 78e4526d55adc049eacc6031fafd66fbe9a7e315 (diff) | |
download | uxp-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.cpp | 4 | ||||
-rw-r--r-- | dom/base/nsGlobalWindow.cpp | 13 | ||||
-rw-r--r-- | dom/base/nsGlobalWindow.h | 1 | ||||
-rw-r--r-- | dom/base/nsPIDOMWindow.h | 15 | ||||
-rw-r--r-- | dom/events/EventDispatcher.cpp | 15 | ||||
-rw-r--r-- | dom/events/EventDispatcher.h | 8 | ||||
-rw-r--r-- | dom/events/EventListenerManager.cpp | 44 | ||||
-rw-r--r-- | dom/events/EventListenerManager.h | 12 | ||||
-rw-r--r-- | dom/webidl/Window.webidl | 1 |
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; |