Bug 1313943 - Legacy event initializers should all do nothing during dispatch; r?bkelly draft
authorAryeh Gregor <ayg@aryeh.name>
Sun, 30 Oct 2016 21:30:06 +0200
changeset 431576 198f58927365562aba994fea981a3bb3f7bf497b
parent 431500 969c3295d3aa77931cca26eddb047d9d74bd9858
child 535429 95e63c92611922e8ffa43c62219b449f642c8973
push id34070
push userayg@aryeh.name
push dateSun, 30 Oct 2016 19:39:04 +0000
reviewersbkelly
bugs1313943
milestone52.0a1
Bug 1313943 - Legacy event initializers should all do nothing during dispatch; r?bkelly DOM's initEvent says that it must do nothing during dispatch. UI Events says they behave the same as initEvent, so the legacy initializers defined there also shouldn't do anything during dispatch. Previously we only did this for initEvent itself, but other legacy initializers would function normally during dispatch. Edge passes the wpt test that's updated in this commit. Chrome passes all but initCustomEvent. It would be nice to expand the test to have coverage for all our legacy initializers, but the likelihood of real-world compat issues from this behavior is slim enough that I didn't think it was worth the effort. MozReview-Commit-ID: IYLOuwlPGSj
dom/events/ClipboardEvent.cpp
dom/events/CommandEvent.cpp
dom/events/CompositionEvent.cpp
dom/events/CustomEvent.cpp
dom/events/DeviceMotionEvent.cpp
dom/events/DragEvent.cpp
dom/events/FocusEvent.cpp
dom/events/KeyboardEvent.cpp
dom/events/MessageEvent.cpp
dom/events/MouseEvent.cpp
dom/events/MouseScrollEvent.cpp
dom/events/MutationEvent.cpp
dom/events/ScrollAreaEvent.cpp
dom/events/SimpleGestureEvent.cpp
dom/events/StorageEvent.cpp
dom/events/TouchEvent.cpp
dom/events/UIEvent.cpp
dom/events/WheelEvent.cpp
dom/events/XULCommandEvent.cpp
dom/smil/TimeEvent.cpp
testing/web-platform/meta/dom/events/Event-init-while-dispatching.html.ini
--- a/dom/events/ClipboardEvent.cpp
+++ b/dom/events/ClipboardEvent.cpp
@@ -48,16 +48,18 @@ ClipboardEvent::InitClipboardEvent(const
   return rv.StealNSResult();
 }
 
 void
 ClipboardEvent::InitClipboardEvent(const nsAString& aType, bool aCanBubble,
                                    bool aCancelable,
                                    DataTransfer* aClipboardData)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   Event::InitEvent(aType, aCanBubble, aCancelable);
   mEvent->AsClipboardEvent()->mClipboardData = aClipboardData;
 }
 
 already_AddRefed<ClipboardEvent>
 ClipboardEvent::Constructor(const GlobalObject& aGlobal,
                             const nsAString& aType,
                             const ClipboardEventInit& aParam,
--- a/dom/events/CommandEvent.cpp
+++ b/dom/events/CommandEvent.cpp
@@ -46,16 +46,18 @@ CommandEvent::GetCommand(nsAString& aCom
 }
 
 NS_IMETHODIMP
 CommandEvent::InitCommandEvent(const nsAString& aTypeArg,
                                bool aCanBubbleArg,
                                bool aCancelableArg,
                                const nsAString& aCommand)
 {
+  NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
+
   Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
 
   mEvent->AsCommandEvent()->mCommand = NS_Atomize(aCommand);
   return NS_OK;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/events/CompositionEvent.cpp
+++ b/dom/events/CompositionEvent.cpp
@@ -59,16 +59,18 @@ CompositionEvent::GetLocale(nsAString& a
 void
 CompositionEvent::InitCompositionEvent(const nsAString& aType,
                                        bool aCanBubble,
                                        bool aCancelable,
                                        nsGlobalWindow* aView,
                                        const nsAString& aData,
                                        const nsAString& aLocale)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, 0);
   mData = aData;
   mLocale = aLocale;
 }
 
 void
 CompositionEvent::GetRanges(TextClauseArray& aRanges)
 {
--- a/dom/events/CustomEvent.cpp
+++ b/dom/events/CustomEvent.cpp
@@ -71,16 +71,18 @@ CustomEvent::WrapObjectInternal(JSContex
 }
 
 NS_IMETHODIMP
 CustomEvent::InitCustomEvent(const nsAString& aType,
                              bool aCanBubble,
                              bool aCancelable,
                              nsIVariant* aDetail)
 {
+  NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
+
   AutoJSAPI jsapi;
   NS_ENSURE_STATE(jsapi.Init(GetParentObject()));
   JSContext* cx = jsapi.cx();
   JS::Rooted<JS::Value> detail(cx);
 
   if (!aDetail) {
     detail = JS::NullValue();
   } else if (NS_WARN_IF(!VariantToJsval(cx, aDetail, &detail))) {
@@ -97,16 +99,18 @@ CustomEvent::InitCustomEvent(const nsASt
 void
 CustomEvent::InitCustomEvent(JSContext* aCx,
                              const nsAString& aType,
                              bool aCanBubble,
                              bool aCancelable,
                              JS::Handle<JS::Value> aDetail,
                              ErrorResult& aRv)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   Event::InitEvent(aType, aCanBubble, aCancelable);
   mDetail = aDetail;
 }
 
 NS_IMETHODIMP
 CustomEvent::GetDetail(nsIVariant** aDetail)
 {
   if (mDetail.isNull()) {
--- a/dom/events/DeviceMotionEvent.cpp
+++ b/dom/events/DeviceMotionEvent.cpp
@@ -46,16 +46,18 @@ DeviceMotionEvent::InitDeviceMotionEvent
                      bool aCanBubble,
                      bool aCancelable,
                      const DeviceAccelerationInit& aAcceleration,
                      const DeviceAccelerationInit& aAccelIncludingGravity,
                      const DeviceRotationRateInit& aRotationRate,
                      Nullable<double> aInterval,
                      Nullable<uint64_t> aTimeStamp)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   Event::InitEvent(aType, aCanBubble, aCancelable);
 
   mAcceleration = new DeviceAcceleration(this, aAcceleration.mX,
                                          aAcceleration.mY,
                                          aAcceleration.mZ);
 
   mAccelerationIncludingGravity =
     new DeviceAcceleration(this, aAccelIncludingGravity.mX,
--- a/dom/events/DragEvent.cpp
+++ b/dom/events/DragEvent.cpp
@@ -50,16 +50,18 @@ DragEvent::InitDragEvent(const nsAString
                          bool aCtrlKey,
                          bool aAltKey,
                          bool aShiftKey,
                          bool aMetaKey,
                          uint16_t aButton,
                          EventTarget* aRelatedTarget,
                          DataTransfer* aDataTransfer)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
                              aView, aDetail, aScreenX, aScreenY,
                              aClientX, aClientY, aCtrlKey, aAltKey,
                              aShiftKey, aMetaKey, aButton, aRelatedTarget);
   if (mEventIsInternal) {
     mEvent->AsDragEvent()->mDataTransfer = aDataTransfer;
   }
 }
--- a/dom/events/FocusEvent.cpp
+++ b/dom/events/FocusEvent.cpp
@@ -44,16 +44,18 @@ FocusEvent::GetRelatedTarget()
 void
 FocusEvent::InitFocusEvent(const nsAString& aType,
                            bool aCanBubble,
                            bool aCancelable,
                            nsGlobalWindow* aView,
                            int32_t aDetail,
                            EventTarget* aRelatedTarget)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
   mEvent->AsFocusEvent()->mRelatedTarget = aRelatedTarget;
 }
 
 already_AddRefed<FocusEvent>
 FocusEvent::Constructor(const GlobalObject& aGlobal,
                         const nsAString& aType,
                         const FocusEventInit& aParam,
--- a/dom/events/KeyboardEvent.cpp
+++ b/dom/events/KeyboardEvent.cpp
@@ -332,16 +332,18 @@ KeyboardEvent::InitKeyEvent(const nsAStr
                             mozIDOMWindow* aView,
                             bool aCtrlKey,
                             bool aAltKey,
                             bool aShiftKey,
                             bool aMetaKey,
                             uint32_t aKeyCode,
                             uint32_t aCharCode)
 {
+  NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
+
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, 0);
 
   WidgetKeyboardEvent* keyEvent = mEvent->AsKeyboardEvent();
   keyEvent->InitBasicModifiers(aCtrlKey, aAltKey, aShiftKey, aMetaKey);
   keyEvent->mKeyCode = aKeyCode;
   keyEvent->mCharCode = aCharCode;
 
   return NS_OK;
--- a/dom/events/MessageEvent.cpp
+++ b/dom/events/MessageEvent.cpp
@@ -141,16 +141,18 @@ void
 MessageEvent::InitMessageEvent(JSContext* aCx, const nsAString& aType,
                                bool aCanBubble, bool aCancelable,
                                JS::Handle<JS::Value> aData,
                                const nsAString& aOrigin,
                                const nsAString& aLastEventId,
                                const Nullable<WindowProxyOrMessagePort>& aSource,
                                const Sequence<OwningNonNull<MessagePort>>& aPorts)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   Event::InitEvent(aType, aCanBubble, aCancelable);
   mData = aData;
   mozilla::HoldJSObjects(this);
   mOrigin = aOrigin;
   mLastEventId = aLastEventId;
 
   mWindowSource = nullptr;
   mPortSource = nullptr;
--- a/dom/events/MouseEvent.cpp
+++ b/dom/events/MouseEvent.cpp
@@ -62,16 +62,18 @@ MouseEvent::InitMouseEvent(const nsAStri
                            int32_t aClientY,
                            bool aCtrlKey,
                            bool aAltKey,
                            bool aShiftKey,
                            bool aMetaKey,
                            uint16_t aButton,
                            EventTarget* aRelatedTarget)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
 
   switch(mEvent->mClass) {
     case eMouseEventClass:
     case eMouseScrollEventClass:
     case eWheelEventClass:
     case eDragEventClass:
     case ePointerEventClass:
@@ -133,16 +135,18 @@ MouseEvent::InitMouseEvent(const nsAStri
                            int32_t aScreenX,
                            int32_t aScreenY,
                            int32_t aClientX,
                            int32_t aClientY,
                            int16_t aButton,
                            EventTarget* aRelatedTarget,
                            const nsAString& aModifiersList)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   Modifiers modifiers = ComputeModifierState(aModifiersList);
 
   InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail,
                  aScreenX, aScreenY, aClientX, aClientY,
                  (modifiers & MODIFIER_CONTROL) != 0,
                  (modifiers & MODIFIER_ALT) != 0,
                  (modifiers & MODIFIER_SHIFT) != 0,
                  (modifiers & MODIFIER_META) != 0,
@@ -205,16 +209,18 @@ MouseEvent::InitNSMouseEvent(const nsASt
                              bool aAltKey,
                              bool aShiftKey,
                              bool aMetaKey,
                              uint16_t aButton,
                              EventTarget* aRelatedTarget,
                              float aPressure,
                              uint16_t aInputSource)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
                              aView, aDetail, aScreenX, aScreenY,
                              aClientX, aClientY,
                              aCtrlKey, aAltKey, aShiftKey,
                              aMetaKey, aButton, aRelatedTarget);
 
   WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase();
   mouseEventBase->pressure = aPressure;
--- a/dom/events/MouseScrollEvent.cpp
+++ b/dom/events/MouseScrollEvent.cpp
@@ -51,16 +51,18 @@ MouseScrollEvent::InitMouseScrollEvent(c
                                        bool aCtrlKey,
                                        bool aAltKey,
                                        bool aShiftKey,
                                        bool aMetaKey,
                                        uint16_t aButton,
                                        EventTarget* aRelatedTarget,
                                        int32_t aAxis)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail,
                              aScreenX, aScreenY, aClientX, aClientY,
                              aCtrlKey, aAltKey, aShiftKey, aMetaKey, aButton,
                              aRelatedTarget);
   mEvent->AsMouseScrollEvent()->mIsHorizontal =
     (aAxis == nsIDOMMouseScrollEvent::HORIZONTAL_AXIS);
 }
 
--- a/dom/events/MutationEvent.cpp
+++ b/dom/events/MutationEvent.cpp
@@ -91,16 +91,18 @@ MutationEvent::InitMutationEvent(const n
                                  bool aCanBubbleArg,
                                  bool aCancelableArg,
                                  nsIDOMNode* aRelatedNodeArg,
                                  const nsAString& aPrevValueArg,
                                  const nsAString& aNewValueArg,
                                  const nsAString& aAttrNameArg,
                                  uint16_t aAttrChangeArg)
 {
+  NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
+
   Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
 
   InternalMutationEvent* mutation = mEvent->AsMutationEvent();
   mutation->mRelatedNode = aRelatedNodeArg;
   if (!aPrevValueArg.IsEmpty())
     mutation->mPrevAttrValue = NS_Atomize(aPrevValueArg);
   if (!aNewValueArg.IsEmpty())
     mutation->mNewAttrValue = NS_Atomize(aNewValueArg);
--- a/dom/events/ScrollAreaEvent.cpp
+++ b/dom/events/ScrollAreaEvent.cpp
@@ -34,16 +34,18 @@ ScrollAreaEvent::InitScrollAreaEvent(con
                                      bool aCancelable,
                                      nsGlobalWindow* aView,
                                      int32_t aDetail,
                                      float aX,
                                      float aY,
                                      float aWidth,
                                      float aHeight)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   UIEvent::InitUIEvent(aEventType, aCanBubble, aCancelable, aView, aDetail);
   mClientArea->SetRect(aX, aY, aWidth, aHeight);
 }
 
 NS_IMETHODIMP_(void)
 ScrollAreaEvent::Serialize(IPC::Message* aMsg,
                            bool aSerializeInterfaceType)
 {
--- a/dom/events/SimpleGestureEvent.cpp
+++ b/dom/events/SimpleGestureEvent.cpp
@@ -119,16 +119,18 @@ SimpleGestureEvent::InitSimpleGestureEve
                                            bool aMetaKeyArg,
                                            uint16_t aButton,
                                            EventTarget* aRelatedTarget,
                                            uint32_t aAllowedDirectionsArg,
                                            uint32_t aDirectionArg,
                                            double aDeltaArg,
                                            uint32_t aClickCountArg)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   MouseEvent::InitMouseEvent(aTypeArg, aCanBubbleArg, aCancelableArg,
                              aViewArg, aDetailArg,
                              aScreenX, aScreenY, aClientX, aClientY,
                              aCtrlKeyArg, aAltKeyArg, aShiftKeyArg,
                              aMetaKeyArg, aButton, aRelatedTarget);
 
   WidgetSimpleGestureEvent* simpleGestureEvent = mEvent->AsSimpleGestureEvent();
   simpleGestureEvent->mAllowedDirections = aAllowedDirectionsArg;
--- a/dom/events/StorageEvent.cpp
+++ b/dom/events/StorageEvent.cpp
@@ -82,16 +82,18 @@ StorageEvent::Constructor(const GlobalOb
 void
 StorageEvent::InitStorageEvent(const nsAString& aType, bool aCanBubble,
                                bool aCancelable, const nsAString& aKey,
                                const nsAString& aOldValue,
                                const nsAString& aNewValue,
                                const nsAString& aURL,
                                DOMStorage* aStorageArea)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   InitEvent(aType, aCanBubble, aCancelable);
   mKey = aKey;
   mOldValue = aOldValue;
   mNewValue = aNewValue;
   mUrl = aURL;
   mStorageArea = aStorageArea;
 }
 
--- a/dom/events/TouchEvent.cpp
+++ b/dom/events/TouchEvent.cpp
@@ -89,16 +89,18 @@ TouchEvent::InitTouchEvent(const nsAStri
                            bool aCtrlKey,
                            bool aAltKey,
                            bool aShiftKey,
                            bool aMetaKey,
                            TouchList* aTouches,
                            TouchList* aTargetTouches,
                            TouchList* aChangedTouches)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
   mEvent->AsInputEvent()->InitBasicModifiers(aCtrlKey, aAltKey,
                                              aShiftKey, aMetaKey);
   mTouches = aTouches;
   mTargetTouches = aTargetTouches;
   mChangedTouches = aChangedTouches;
 }
 
--- a/dom/events/UIEvent.cpp
+++ b/dom/events/UIEvent.cpp
@@ -164,16 +164,18 @@ UIEvent::InitUIEvent(const nsAString& ty
 
 NS_IMETHODIMP
 UIEvent::InitUIEvent(const nsAString& typeArg,
                      bool canBubbleArg,
                      bool cancelableArg,
                      mozIDOMWindow* viewArg,
                      int32_t detailArg)
 {
+  NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
+
   Event::InitEvent(typeArg, canBubbleArg, cancelableArg);
 
   mDetail = detailArg;
   mView = viewArg ? nsPIDOMWindowInner::From(viewArg)->GetOuterWindow() :
                     nullptr;
 
   return NS_OK;
 }
--- a/dom/events/WheelEvent.cpp
+++ b/dom/events/WheelEvent.cpp
@@ -55,16 +55,18 @@ WheelEvent::InitWheelEvent(const nsAStri
                            uint16_t aButton,
                            EventTarget* aRelatedTarget,
                            const nsAString& aModifiersList,
                            double aDeltaX,
                            double aDeltaY,
                            double aDeltaZ,
                            uint32_t aDeltaMode)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail,
                              aScreenX, aScreenY, aClientX, aClientY, aButton,
                              aRelatedTarget, aModifiersList);
 
   WidgetWheelEvent* wheelEvent = mEvent->AsWheelEvent();
   wheelEvent->mDeltaX = aDeltaX;
   wheelEvent->mDeltaY = aDeltaY;
   wheelEvent->mDeltaZ = aDeltaZ;
--- a/dom/events/XULCommandEvent.cpp
+++ b/dom/events/XULCommandEvent.cpp
@@ -108,16 +108,18 @@ XULCommandEvent::InitCommandEvent(const 
                                   mozIDOMWindow* aView,
                                   int32_t aDetail,
                                   bool aCtrlKey,
                                   bool aAltKey,
                                   bool aShiftKey,
                                   bool aMetaKey,
                                   nsIDOMEvent* aSourceEvent)
 {
+  NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
+
   auto* view = nsGlobalWindow::Cast(nsPIDOMWindowInner::From(aView));
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, view, aDetail);
 
   mEvent->AsInputEvent()->InitBasicModifiers(aCtrlKey, aAltKey,
                                              aShiftKey, aMetaKey);
   mSourceEvent = aSourceEvent;
 
   return NS_OK;
--- a/dom/smil/TimeEvent.cpp
+++ b/dom/smil/TimeEvent.cpp
@@ -51,16 +51,18 @@ TimeEvent::GetDetail(int32_t* aDetail)
   *aDetail = mDetail;
   return NS_OK;
 }
 
 void
 TimeEvent::InitTimeEvent(const nsAString& aType, nsGlobalWindow* aView,
                          int32_t aDetail)
 {
+  NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
+
   Event::InitEvent(aType, false /*doesn't bubble*/, false /*can't cancel*/);
   mDetail = aDetail;
   mView = aView ? aView->GetOuterWindow() : nullptr;
 }
 
 } // namespace dom
 } // namespace mozilla
 
--- a/testing/web-platform/meta/dom/events/Event-init-while-dispatching.html.ini
+++ b/testing/web-platform/meta/dom/events/Event-init-while-dispatching.html.ini
@@ -1,14 +1,6 @@
 [Event-init-while-dispatching.html]
   type: testharness
   [Calling initKeyboardEvent while dispatching.]
     expected: FAIL
-
-  [Calling initMouseEvent while dispatching.]
-    expected: FAIL
+    bug: https://github.com/w3c/web-platform-tests/pull/4117
 
-  [Calling initCustomEvent while dispatching.]
-    expected: FAIL
-
-  [Calling initUIEvent while dispatching.]
-    expected: FAIL
-