# Global Metrics

path: .metrics.halstead.N2
old: 157.0
new: 798.0
path: .metrics.halstead.effort
old: 102488.74668784192
new: 752543.2305163763
path: .metrics.halstead.level
old: 0.02229299363057325
new: 0.01904761904761905
path: .metrics.halstead.n2
old: 42.0
new: 190.0
path: .metrics.halstead.n1
old: 24.0
new: 25.0
path: .metrics.halstead.bugs
old: 0.7300112172205769
new: 2.757822946889932
path: .metrics.halstead.purity_ratio
old: 0.890255110513269
new: 0.8401994434201342
path: .metrics.halstead.N1
old: 221.0
new: 1052.0
path: .metrics.halstead.difficulty
old: 44.857142857142854
new: 52.5
path: .metrics.halstead.volume
old: 2284.7809771174952
new: 14334.1567717405
path: .metrics.halstead.vocabulary
old: 66.0
new: 215.0
path: .metrics.halstead.length
old: 378.0
new: 1850.0
path: .metrics.halstead.estimated_program_length
old: 336.5164317740157
new: 1554.3689703272482
path: .metrics.halstead.time
old: 5693.819260435663
new: 41807.95725090979
path: .metrics.cognitive.average
old: 1.6666666666666667
new: 0.3541666666666667
path: .metrics.cognitive.sum
old: 15.0
new: 17.0
path: .metrics.nom.functions
old: 9.0
new: 48.0
path: .metrics.nom.total
old: 9.0
new: 48.0
path: .metrics.nargs.average
old: 0.3333333333333333
new: 0.9791666666666666
path: .metrics.nargs.sum
old: 3.0
new: 47.0
path: .metrics.nexits.average
old: 1.0
new: 0.5208333333333334
path: .metrics.nexits.sum
old: 9.0
new: 25.0
path: .metrics.cyclomatic.average
old: 2.2
new: 1.34375
path: .metrics.cyclomatic.sum
old: 22.0
new: 86.0
path: .metrics.mi.mi_visual_studio
old: 25.927604234906788
new: 0.0
path: .metrics.mi.mi_original
old: 44.33620324169061
new: -5.286691814495967
path: .metrics.mi.mi_sei
old: 27.8324926820026
new: -39.88820869025754
path: .metrics.loc.blank
old: 13.0
new: 102.0
path: .metrics.loc.cloc
old: 45.0
new: 178.0
path: .metrics.loc.sloc
old: 152.0
new: 727.0
path: .metrics.loc.lloc
old: 61.0
new: 98.0
path: .metrics.loc.ploc
old: 94.0
new: 447.0

# Spaces Data

## Minimal test - lines (27, 725)

path: .spaces[1].metrics.cyclomatic.average
old: 1.0
new: 1.3859649122807018
path: .spaces[1].metrics.cyclomatic.sum
old: 1.0
new: 79.0
path: .spaces[1].metrics.nargs.sum
old: 0.0
new: 47.0
path: .spaces[1].metrics.nargs.average
old: 0.0
new: 0.9791666666666666
path: .spaces[1].metrics.cognitive.sum
old: 0.0
new: 17.0
path: .spaces[1].metrics.cognitive.average
old: 0.0
new: 0.3541666666666667
path: .spaces[1].metrics.loc.blank
old: 0.0
new: 98.0
path: .spaces[1].metrics.loc.lloc
old: 3.0
new: 98.0
path: .spaces[1].metrics.loc.ploc
old: 5.0
new: 431.0
path: .spaces[1].metrics.loc.cloc
old: 0.0
new: 170.0
path: .spaces[1].metrics.loc.sloc
old: 5.0
new: 699.0
path: .spaces[1].metrics.nom.functions
old: 1.0
new: 48.0
path: .spaces[1].metrics.nom.total
old: 1.0
new: 48.0
path: .spaces[1].metrics.halstead.estimated_program_length
old: 27.11941547876375
new: 1500.4318046588585
path: .spaces[1].metrics.halstead.n1
old: 6.0
new: 25.0
path: .spaces[1].metrics.halstead.n2
old: 5.0
new: 184.0
path: .spaces[1].metrics.halstead.bugs
old: 0.011371826749065804
new: 2.7612725744838325
path: .spaces[1].metrics.halstead.difficulty
old: 3.6
new: 53.39673913043478
path: .spaces[1].metrics.halstead.length
old: 16.0
new: 1832.0
path: .spaces[1].metrics.halstead.volume
old: 55.35090589819676
new: 14119.881929972176
path: .spaces[1].metrics.halstead.level
old: 0.2777777777777778
new: 0.018727735368956742
path: .spaces[1].metrics.halstead.purity_ratio
old: 1.6949634674227343
new: 0.8190129938094206
path: .spaces[1].metrics.halstead.effort
old: 199.26326123350833
new: 753955.6519672642
path: .spaces[1].metrics.halstead.N2
old: 6.0
new: 786.0
path: .spaces[1].metrics.halstead.time
old: 11.070181179639352
new: 41886.42510929246
path: .spaces[1].metrics.halstead.vocabulary
old: 11.0
new: 209.0
path: .spaces[1].metrics.halstead.N1
old: 10.0
new: 1046.0
path: .spaces[1].metrics.nexits.sum
old: 0.0
new: 25.0
path: .spaces[1].metrics.nexits.average
old: 0.0
new: 0.5208333333333334
path: .spaces[1].metrics.mi.mi_original
old: 123.8259020846929
new: -2.9621055995716006
path: .spaces[1].metrics.mi.mi_sei
old: 103.0439827385805
new: -37.33985310039714
path: .spaces[1].metrics.mi.mi_visual_studio
old: 72.41280823666251
new: 0.0

### Code

    namespace mozilla {
    class WidgetPointerEventHolder final {
     public:
      nsTArray mEvents;
      NS_INLINE_DECL_REFCOUNTING(WidgetPointerEventHolder)

     private:
      virtual ~WidgetPointerEventHolder() = default;
    };

    /******************************************************************************
     * mozilla::WidgetPointerHelper
     ******************************************************************************/

    class WidgetPointerHelper {
     public:
      uint32_t pointerId;
      uint32_t tiltX;
      uint32_t tiltY;
      uint32_t twist;
      float tangentialPressure;
      bool convertToPointer;
      RefPtr mCoalescedWidgetEvents;

      WidgetPointerHelper()
          : pointerId(0),
            tiltX(0),
            tiltY(0),
            twist(0),
            tangentialPressure(0),
            convertToPointer(true) {}

      WidgetPointerHelper(uint32_t aPointerId, uint32_t aTiltX, uint32_t aTiltY,
                          uint32_t aTwist = 0, float aTangentialPressure = 0)
          : pointerId(aPointerId),
            tiltX(aTiltX),
            tiltY(aTiltY),
            twist(aTwist),
            tangentialPressure(aTangentialPressure),
            convertToPointer(true) {}

      explicit WidgetPointerHelper(const WidgetPointerHelper& aHelper) = default;

      void AssignPointerHelperData(const WidgetPointerHelper& aEvent,
                                   bool aCopyCoalescedEvents = false) {
        pointerId = aEvent.pointerId;
        tiltX = aEvent.tiltX;
        tiltY = aEvent.tiltY;
        twist = aEvent.twist;
        tangentialPressure = aEvent.tangentialPressure;
        convertToPointer = aEvent.convertToPointer;
        if (aCopyCoalescedEvents) {
          mCoalescedWidgetEvents = aEvent.mCoalescedWidgetEvents;
        }
      }
    };

    /******************************************************************************
     * mozilla::WidgetMouseEventBase
     ******************************************************************************/

    class WidgetMouseEventBase : public WidgetInputEvent {
     private:
      friend class dom::PBrowserParent;
      friend class dom::PBrowserChild;
      friend class dom::PBrowserBridgeParent;

     protected:
      WidgetMouseEventBase()
          : mPressure(0),
            mButton(0),
            mButtons(0),
            mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {}
      // Including MouseEventBinding.h here leads to an include loop, so
      // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE.

      WidgetMouseEventBase(bool aIsTrusted, EventMessage aMessage,
                           nsIWidget* aWidget, EventClassID aEventClassID)
          : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
            mPressure(0),
            mButton(0),
            mButtons(0),
            mInputSource(/* MouseEvent_Binding::MOZ_SOURCE_MOUSE = */ 1) {}
      // Including MouseEventBinding.h here leads to an include loop, so
      // we have to hardcode MouseEvent_Binding::MOZ_SOURCE_MOUSE.

     public:
      virtual WidgetMouseEventBase* AsMouseEventBase() override { return this; }

      virtual WidgetEvent* Duplicate() const override {
        MOZ_CRASH("WidgetMouseEventBase must not be most-subclass");
      }

      // ID of the canvas HitRegion
      nsString mRegion;

      // Finger or touch pressure of event. It ranges between 0.0 and 1.0.
      float mPressure;

      // Pressed button ID of mousedown or mouseup event.
      // This is set only when pressing a button causes the event.
      int16_t mButton;

      // Flags of all pressed buttons at the event fired.
      // This is set at any mouse event, don't be confused with |mButton|.
      int16_t mButtons;

      // Possible values a in MouseEvent
      uint16_t mInputSource;

      bool IsLeftButtonPressed() const {
        return !!(mButtons & MouseButtonsFlag::ePrimaryFlag);
      }
      bool IsRightButtonPressed() const {
        return !!(mButtons & MouseButtonsFlag::eSecondaryFlag);
      }
      bool IsMiddleButtonPressed() const {
        return !!(mButtons & MouseButtonsFlag::eMiddleFlag);
      }
      bool Is4thButtonPressed() const {
        return !!(mButtons & MouseButtonsFlag::e4thFlag);
      }
      bool Is5thButtonPressed() const {
        return !!(mButtons & MouseButtonsFlag::e5thFlag);
      }

      void AssignMouseEventBaseData(const WidgetMouseEventBase& aEvent,
                                    bool aCopyTargets) {
        AssignInputEventData(aEvent, aCopyTargets);

        mButton = aEvent.mButton;
        mButtons = aEvent.mButtons;
        mPressure = aEvent.mPressure;
        mInputSource = aEvent.mInputSource;
      }

      /**
       * Returns true if left click event.
       */
      bool IsLeftClickEvent() const {
        return mMessage == eMouseClick && mButton == MouseButton::ePrimary;
      }
    };

    /******************************************************************************
     * mozilla::WidgetMouseEvent
     ******************************************************************************/

    class WidgetMouseEvent : public WidgetMouseEventBase,
                             public WidgetPointerHelper {
     private:
      friend class dom::PBrowserParent;
      friend class dom::PBrowserChild;
      friend class dom::PBrowserBridgeParent;

     public:
      typedef bool ReasonType;
      enum Reason : ReasonType { eReal, eSynthesized };

      typedef uint8_t ContextMenuTriggerType;
      enum ContextMenuTrigger : ContextMenuTriggerType {
        eNormal,
        eContextMenuKey,
        eControlClick
      };

      typedef uint8_t ExitFromType;
      enum ExitFrom : ExitFromType {
        ePlatformChild,
        ePlatformTopLevel,
        ePuppet,
        ePuppetParentToPuppetChild
      };

     protected:
      WidgetMouseEvent()
          : mReason(eReal),
            mContextMenuTrigger(eNormal),
            mIgnoreRootScrollFrame(false),
            mClickCount(0),
            mUseLegacyNonPrimaryDispatch(false) {}

      WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
                       EventClassID aEventClassID, Reason aReason)
          : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, aEventClassID),
            mReason(aReason),
            mContextMenuTrigger(eNormal),
            mIgnoreRootScrollFrame(false),
            mClickCount(0),
            mUseLegacyNonPrimaryDispatch(false) {}

     public:
      virtual WidgetMouseEvent* AsMouseEvent() override { return this; }

      WidgetMouseEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
                       Reason aReason,
                       ContextMenuTrigger aContextMenuTrigger = eNormal)
          : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eMouseEventClass),
            mReason(aReason),
            mContextMenuTrigger(aContextMenuTrigger),
            mIgnoreRootScrollFrame(false),
            mClickCount(0),
            mUseLegacyNonPrimaryDispatch(false) {
        if (aMessage == eContextMenu) {
          mButton = (mContextMenuTrigger == eNormal) ? MouseButton::eSecondary
                                                     : MouseButton::ePrimary;
        }
      }

    #ifdef DEBUG
      virtual ~WidgetMouseEvent() {
        NS_WARNING_ASSERTION(
            mMessage != eContextMenu ||
                (mButton == ((mContextMenuTrigger == eNormal)
                                 ? MouseButton::eSecondary
                                 : MouseButton::ePrimary) &&
                 (mContextMenuTrigger != eControlClick || IsControl())),
            "Wrong button set to eContextMenu event?");
      }
    #endif

      virtual WidgetEvent* Duplicate() const override {
        MOZ_ASSERT(mClass == eMouseEventClass,
                   "Duplicate() must be overridden by sub class");
        // Not copying widget, it is a weak reference.
        WidgetMouseEvent* result = new WidgetMouseEvent(
            false, mMessage, nullptr, mReason, mContextMenuTrigger);
        result->AssignMouseEventData(*this, true);
        result->mFlags = mFlags;
        return result;
      }

      // If during mouseup handling we detect that click event might need to be
      // dispatched, this is setup to be the target of the click event.
      nsCOMPtr mClickTarget;

      // mReason indicates the reason why the event is fired:
      // - Representing mouse operation.
      // - Synthesized for emulating mousemove event when the content under the
      //   mouse cursor is scrolled.
      Reason mReason;

      // mContextMenuTrigger is valid only when mMessage is eContextMenu.
      // This indicates if the context menu event is caused by context menu key or
      // other reasons (typically, a click of right mouse button).
      ContextMenuTrigger mContextMenuTrigger;

      // mExitFrom contains a value only when mMessage is eMouseExitFromWidget.
      // This indicates if the mouse cursor exits from a top level platform widget,
      // a child widget or a puppet widget.
      Maybe mExitFrom;

      // Whether the event should ignore scroll frame bounds during dispatch.
      bool mIgnoreRootScrollFrame;

      // mClickCount may be non-zero value when mMessage is eMouseDown, eMouseUp,
      // eMouseClick or eMouseDoubleClick. The number is count of mouse clicks.
      // Otherwise, this must be 0.
      uint32_t mClickCount;

      // Indicates whether the event should dispatch click events for non-primary
      // mouse buttons on window and document.
      bool mUseLegacyNonPrimaryDispatch;

      void AssignMouseEventData(const WidgetMouseEvent& aEvent, bool aCopyTargets) {
        AssignMouseEventBaseData(aEvent, aCopyTargets);
        AssignPointerHelperData(aEvent, /* aCopyCoalescedEvents */ true);

        mExitFrom = aEvent.mExitFrom;
        mIgnoreRootScrollFrame = aEvent.mIgnoreRootScrollFrame;
        mClickCount = aEvent.mClickCount;
        mUseLegacyNonPrimaryDispatch = aEvent.mUseLegacyNonPrimaryDispatch;
      }

      /**
       * Returns true if the event is a context menu event caused by key.
       */
      bool IsContextMenuKeyEvent() const {
        return mMessage == eContextMenu && mContextMenuTrigger == eContextMenuKey;
      }

      /**
       * Returns true if the event is a real mouse event.  Otherwise, i.e., it's
       * a synthesized event by scroll or something, returns false.
       */
      bool IsReal() const { return mReason == eReal; }

      /**
       * Returns true if middle click paste is enabled.
       */
      static bool IsMiddleClickPasteEnabled();
    };

    /******************************************************************************
     * mozilla::WidgetDragEvent
     ******************************************************************************/

    class WidgetDragEvent : public WidgetMouseEvent {
     private:
      friend class mozilla::dom::PBrowserParent;
      friend class mozilla::dom::PBrowserChild;

     protected:
      WidgetDragEvent()
          : mUserCancelled(false), mDefaultPreventedOnContent(false) {}

     public:
      virtual WidgetDragEvent* AsDragEvent() override { return this; }

      WidgetDragEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
          : WidgetMouseEvent(aIsTrusted, aMessage, aWidget, eDragEventClass, eReal),
            mUserCancelled(false),
            mDefaultPreventedOnContent(false) {}

      virtual WidgetEvent* Duplicate() const override {
        MOZ_ASSERT(mClass == eDragEventClass,
                   "Duplicate() must be overridden by sub class");
        // Not copying widget, it is a weak reference.
        WidgetDragEvent* result = new WidgetDragEvent(false, mMessage, nullptr);
        result->AssignDragEventData(*this, true);
        result->mFlags = mFlags;
        return result;
      }

      // The dragging data.
      nsCOMPtr mDataTransfer;

      // If this is true, user has cancelled the drag operation.
      bool mUserCancelled;
      // If this is true, the drag event's preventDefault() is called on content.
      bool mDefaultPreventedOnContent;

      // XXX Not tested by test_assign_event_data.html
      void AssignDragEventData(const WidgetDragEvent& aEvent, bool aCopyTargets) {
        AssignMouseEventData(aEvent, aCopyTargets);

        mDataTransfer = aEvent.mDataTransfer;
        // XXX mUserCancelled isn't copied, is this intentionally?
        mUserCancelled = false;
        mDefaultPreventedOnContent = aEvent.mDefaultPreventedOnContent;
      }

      /**
       * Should be called before dispatching the DOM tree if this event is
       * synthesized for tests because drop effect is initialized before
       * dispatching from widget if it's not synthesized event, but synthesized
       * events are not initialized in the path.
       */
      void InitDropEffectForTests();
    };

    /******************************************************************************
     * mozilla::WidgetMouseScrollEvent
     *
     * This is used for legacy DOM mouse scroll events, i.e.,
     * DOMMouseScroll and MozMousePixelScroll event.  These events are NOT hanbled
     * by ESM even if widget dispatches them.  Use new WidgetWheelEvent instead.
     ******************************************************************************/

    class WidgetMouseScrollEvent : public WidgetMouseEventBase {
     private:
      WidgetMouseScrollEvent() : mDelta(0), mIsHorizontal(false) {}

     public:
      virtual WidgetMouseScrollEvent* AsMouseScrollEvent() override { return this; }

      WidgetMouseScrollEvent(bool aIsTrusted, EventMessage aMessage,
                             nsIWidget* aWidget)
          : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget,
                                 eMouseScrollEventClass),
            mDelta(0),
            mIsHorizontal(false) {}

      virtual WidgetEvent* Duplicate() const override {
        MOZ_ASSERT(mClass == eMouseScrollEventClass,
                   "Duplicate() must be overridden by sub class");
        // Not copying widget, it is a weak reference.
        WidgetMouseScrollEvent* result =
            new WidgetMouseScrollEvent(false, mMessage, nullptr);
        result->AssignMouseScrollEventData(*this, true);
        result->mFlags = mFlags;
        return result;
      }

      // The delta value of mouse scroll event.
      // If the event message is eLegacyMouseLineOrPageScroll, the value indicates
      // scroll amount in lines.  However, if the value is
      // UIEvent::SCROLL_PAGE_UP or UIEvent::SCROLL_PAGE_DOWN, the
      // value inducates one page scroll.  If the event message is
      // eLegacyMousePixelScroll, the value indicates scroll amount in pixels.
      int32_t mDelta;

      // If this is true, it may cause to scroll horizontally.
      // Otherwise, vertically.
      bool mIsHorizontal;

      void AssignMouseScrollEventData(const WidgetMouseScrollEvent& aEvent,
                                      bool aCopyTargets) {
        AssignMouseEventBaseData(aEvent, aCopyTargets);

        mDelta = aEvent.mDelta;
        mIsHorizontal = aEvent.mIsHorizontal;
      }
    };

    /******************************************************************************
     * mozilla::WidgetWheelEvent
     ******************************************************************************/

    class WidgetWheelEvent : public WidgetMouseEventBase {
     private:
      friend class mozilla::dom::PBrowserParent;
      friend class mozilla::dom::PBrowserChild;

      WidgetWheelEvent()
          : mDeltaX(0.0),
            mDeltaY(0.0),
            mDeltaZ(0.0),
            mOverflowDeltaX(0.0),
            mOverflowDeltaY(0.0)
            // Including WheelEventBinding.h here leads to an include loop, so
            // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL.
            ,
            mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0),
            mLineOrPageDeltaX(0),
            mLineOrPageDeltaY(0),
            mScrollType(SCROLL_DEFAULT),
            mCustomizedByUserPrefs(false),
            mMayHaveMomentum(false),
            mIsMomentum(false),
            mIsNoLineOrPageDelta(false),
            mViewPortIsOverscrolled(false),
            mCanTriggerSwipe(false),
            mAllowToOverrideSystemScrollSpeed(false),
            mDeltaValuesHorizontalizedForDefaultHandler(false) {}

     public:
      virtual WidgetWheelEvent* AsWheelEvent() override { return this; }

      WidgetWheelEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
          : WidgetMouseEventBase(aIsTrusted, aMessage, aWidget, eWheelEventClass),
            mDeltaX(0.0),
            mDeltaY(0.0),
            mDeltaZ(0.0),
            mOverflowDeltaX(0.0),
            mOverflowDeltaY(0.0)
            // Including WheelEventBinding.h here leads to an include loop, so
            // we have to hardcode WheelEvent_Binding::DOM_DELTA_PIXEL.
            ,
            mDeltaMode(/* WheelEvent_Binding::DOM_DELTA_PIXEL = */ 0),
            mLineOrPageDeltaX(0),
            mLineOrPageDeltaY(0),
            mScrollType(SCROLL_DEFAULT),
            mCustomizedByUserPrefs(false),
            mMayHaveMomentum(false),
            mIsMomentum(false),
            mIsNoLineOrPageDelta(false),
            mViewPortIsOverscrolled(false),
            mCanTriggerSwipe(false),
            mAllowToOverrideSystemScrollSpeed(true),
            mDeltaValuesHorizontalizedForDefaultHandler(false) {}

      virtual WidgetEvent* Duplicate() const override {
        MOZ_ASSERT(mClass == eWheelEventClass,
                   "Duplicate() must be overridden by sub class");
        // Not copying widget, it is a weak reference.
        WidgetWheelEvent* result = new WidgetWheelEvent(false, mMessage, nullptr);
        result->AssignWheelEventData(*this, true);
        result->mFlags = mFlags;
        return result;
      }

      // On OS X, scroll gestures that start at the edge of the scrollable range
      // can result in a swipe gesture. For the first wheel event of such a
      // gesture, call TriggersSwipe() after the event has been processed
      // in order to find out whether a swipe should be started.
      bool TriggersSwipe() const {
        return mCanTriggerSwipe && mViewPortIsOverscrolled &&
               this->mOverflowDeltaX != 0.0;
      }

      // NOTE: mDeltaX, mDeltaY and mDeltaZ may be customized by
      //       mousewheel.*.delta_multiplier_* prefs which are applied by
      //       EventStateManager.  So, after widget dispatches this event,
      //       these delta values may have different values than before.
      double mDeltaX;
      double mDeltaY;
      double mDeltaZ;

      enum class DeltaModeCheckingState : uint8_t {
        // Neither deltaMode nor the delta values have been accessed.
        Unknown,
        // The delta values have been accessed, without checking deltaMode first.
        Unchecked,
        // The deltaMode has been checked.
        Checked,
      };

      // For compat reasons, we might expose a DOM_DELTA_LINE event as
      // DOM_DELTA_PIXEL instead. Whether we do that depends on whether the event
      // has been asked for the deltaMode before the deltas. If it has, we assume
      // that the page will correctly handle DOM_DELTA_LINE. This variable tracks
      // that state. See bug 1392460.
      DeltaModeCheckingState mDeltaModeCheckingState =
          DeltaModeCheckingState::Unknown;

      // The amount of scrolling per line or page, without accounting for mouse
      // wheel transactions etc.
      //
      // Computed by EventStateManager::DeltaAccumulator::InitLineOrPageDelta.
      nsSize mScrollAmount;

      // overflowed delta values for scroll, these values are set by
      // EventStateManger.  If the default action of the wheel event isn't scroll,
      // these values are always zero.  Otherwise, remaining delta values which are
      // not used by scroll are set.
      // NOTE: mDeltaX, mDeltaY and mDeltaZ may be modified by EventStateManager.
      //       However, mOverflowDeltaX and mOverflowDeltaY indicate unused original
      //       delta values which are not applied the delta_multiplier prefs.
      //       So, if widget wanted to know the actual direction to be scrolled,
      //       it would need to check the mDeltaX and mDeltaY.
      double mOverflowDeltaX;
      double mOverflowDeltaY;

      // Should be one of WheelEvent_Binding::DOM_DELTA_*
      uint32_t mDeltaMode;

      // If widget sets mLineOrPageDelta, EventStateManager will dispatch
      // eLegacyMouseLineOrPageScroll event for compatibility.  Note that the delta
      // value means pages if the mDeltaMode is DOM_DELTA_PAGE, otherwise, lines.
      int32_t mLineOrPageDeltaX;
      int32_t mLineOrPageDeltaY;

      // When the default action for an wheel event is moving history or zooming,
      // need to chose a delta value for doing it.
      int32_t GetPreferredIntDelta() {
        if (!mLineOrPageDeltaX && !mLineOrPageDeltaY) {
          return 0;
        }
        if (mLineOrPageDeltaY && !mLineOrPageDeltaX) {
          return mLineOrPageDeltaY;
        }
        if (mLineOrPageDeltaX && !mLineOrPageDeltaY) {
          return mLineOrPageDeltaX;
        }
        if ((mLineOrPageDeltaX < 0 && mLineOrPageDeltaY > 0) ||
            (mLineOrPageDeltaX > 0 && mLineOrPageDeltaY < 0)) {
          return 0;  // We cannot guess the answer in this case.
        }
        return (Abs(mLineOrPageDeltaX) > Abs(mLineOrPageDeltaY))
                   ? mLineOrPageDeltaX
                   : mLineOrPageDeltaY;
      }

      // Scroll type
      // The default value is SCROLL_DEFAULT, which means EventStateManager will
      // select preferred scroll type automatically.
      enum ScrollType : uint8_t {
        SCROLL_DEFAULT,
        SCROLL_SYNCHRONOUSLY,
        SCROLL_ASYNCHRONOUSELY,
        SCROLL_SMOOTHLY
      };
      ScrollType mScrollType;

      // If the delta values are computed from prefs, this value is true.
      // Otherwise, i.e., they are computed from native events, false.
      bool mCustomizedByUserPrefs;

      // true if the momentum events directly tied to this event may follow it.
      bool mMayHaveMomentum;
      // true if the event is caused by momentum.
      bool mIsMomentum;

      // If device event handlers don't know when they should set mLineOrPageDeltaX
      // and mLineOrPageDeltaY, this is true.  Otherwise, false.
      // If mIsNoLineOrPageDelta is true, ESM will generate
      // eLegacyMouseLineOrPageScroll events when accumulated delta values reach
      // a line height.
      bool mIsNoLineOrPageDelta;

      // Whether or not the parent of the currently overscrolled frame is the
      // ViewPort. This is false in situations when an element on the page is being
      // overscrolled (such as a text field), but true when the 'page' is being
      // overscrolled.
      bool mViewPortIsOverscrolled;

      // The wheel event can trigger a swipe to start if it's overscrolling the
      // viewport.
      bool mCanTriggerSwipe;

      // If mAllowToOverrideSystemScrollSpeed is true, the scroll speed may be
      // overridden.  Otherwise, the scroll speed won't be overridden even if
      // it's enabled by the pref.
      bool mAllowToOverrideSystemScrollSpeed;

      // After the event's default action handler has adjusted its delta's values
      // for horizontalizing a vertical wheel scroll, this variable will be set to
      // true.
      bool mDeltaValuesHorizontalizedForDefaultHandler;

      void AssignWheelEventData(const WidgetWheelEvent& aEvent, bool aCopyTargets) {
        AssignMouseEventBaseData(aEvent, aCopyTargets);

        mDeltaX = aEvent.mDeltaX;
        mDeltaY = aEvent.mDeltaY;
        mDeltaZ = aEvent.mDeltaZ;
        mDeltaMode = aEvent.mDeltaMode;
        mScrollAmount = aEvent.mScrollAmount;
        mCustomizedByUserPrefs = aEvent.mCustomizedByUserPrefs;
        mMayHaveMomentum = aEvent.mMayHaveMomentum;
        mIsMomentum = aEvent.mIsMomentum;
        mIsNoLineOrPageDelta = aEvent.mIsNoLineOrPageDelta;
        mLineOrPageDeltaX = aEvent.mLineOrPageDeltaX;
        mLineOrPageDeltaY = aEvent.mLineOrPageDeltaY;
        mScrollType = aEvent.mScrollType;
        mOverflowDeltaX = aEvent.mOverflowDeltaX;
        mOverflowDeltaY = aEvent.mOverflowDeltaY;
        mViewPortIsOverscrolled = aEvent.mViewPortIsOverscrolled;
        mCanTriggerSwipe = aEvent.mCanTriggerSwipe;
        mAllowToOverrideSystemScrollSpeed =
            aEvent.mAllowToOverrideSystemScrollSpeed;
        mDeltaValuesHorizontalizedForDefaultHandler =
            aEvent.mDeltaValuesHorizontalizedForDefaultHandler;
      }

      // System scroll speed settings may be too slow at using Gecko.  In such
      // case, we should override the scroll speed computed with system settings.
      // Following methods return preferred delta values which are multiplied by
      // factors specified by prefs.  If system scroll speed shouldn't be
      // overridden (e.g., this feature is disabled by pref), they return raw
      // delta values.
      double OverriddenDeltaX() const;
      double OverriddenDeltaY() const;

      // Compute the overridden delta value.  This may be useful for suppressing
      // too fast scroll by system scroll speed overriding when widget sets
      // mAllowToOverrideSystemScrollSpeed.
      static double ComputeOverriddenDelta(double aDelta, bool aIsForVertical);

     private:
      static bool sInitialized;
      static bool sIsSystemScrollSpeedOverrideEnabled;
      static int32_t sOverrideFactorX;
      static int32_t sOverrideFactorY;
      static void Initialize();
    };

    /******************************************************************************
     * mozilla::WidgetPointerEvent
     ******************************************************************************/

    class WidgetPointerEvent : public WidgetMouseEvent {
      friend class mozilla::dom::PBrowserParent;
      friend class mozilla::dom::PBrowserChild;

      WidgetPointerEvent() : mWidth(1), mHeight(1), mIsPrimary(true) {}

     public:
      virtual WidgetPointerEvent* AsPointerEvent() override { return this; }

      WidgetPointerEvent(bool aIsTrusted, EventMessage aMsg, nsIWidget* w)
          : WidgetMouseEvent(aIsTrusted, aMsg, w, ePointerEventClass, eReal),
            mWidth(1),
            mHeight(1),
            mIsPrimary(true) {}

      explicit WidgetPointerEvent(const WidgetMouseEvent& aEvent)
          : WidgetMouseEvent(aEvent), mWidth(1), mHeight(1), mIsPrimary(true) {
        mClass = ePointerEventClass;
      }

      virtual WidgetEvent* Duplicate() const override {
        MOZ_ASSERT(mClass == ePointerEventClass,
                   "Duplicate() must be overridden by sub class");
        // Not copying widget, it is a weak reference.
        WidgetPointerEvent* result =
            new WidgetPointerEvent(false, mMessage, nullptr);
        result->AssignPointerEventData(*this, true);
        result->mFlags = mFlags;
        return result;
      }

      uint32_t mWidth;
      uint32_t mHeight;
      bool mIsPrimary;

      // XXX Not tested by test_assign_event_data.html
      void AssignPointerEventData(const WidgetPointerEvent& aEvent,
                                  bool aCopyTargets) {
        AssignMouseEventData(aEvent, aCopyTargets);

        mWidth = aEvent.mWidth;
        mHeight = aEvent.mHeight;
        mIsPrimary = aEvent.mIsPrimary;
      }
    };

    }  // namespace mozilla

## Minimal test - lines (16, 25)

path: .spaces[0].metrics.loc.blank
old: 0.0
new: 1.0
path: .spaces[0].metrics.loc.ploc
old: 4.0
new: 8.0
path: .spaces[0].metrics.loc.sloc
old: 4.0
new: 10.0
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 1.0
path: .spaces[0].metrics.loc.lloc
old: 2.0
new: 0.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].metrics.halstead.effort
old: 188.2105312878607
new: 36.0
path: .spaces[0].metrics.halstead.time
old: 10.456140627103371
new: 2.0
path: .spaces[0].metrics.halstead.volume
old: 53.77443751081734
new: 36.0
path: .spaces[0].metrics.halstead.vocabulary
old: 12.0
new: 8.0
path: .spaces[0].metrics.halstead.difficulty
old: 3.5
new: 1.0
path: .spaces[0].metrics.halstead.N1
old: 8.0
new: 6.0
path: .spaces[0].metrics.halstead.N2
old: 7.0
new: 6.0
path: .spaces[0].metrics.halstead.length
old: 15.0
new: 12.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 2.067970000576925
new: 1.4591479170272448
path: .spaces[0].metrics.halstead.n1
old: 6.0
new: 2.0
path: .spaces[0].metrics.halstead.bugs
old: 0.010947325359591292
new: 0.0036342411856642785
path: .spaces[0].metrics.halstead.estimated_program_length
old: 31.019550008653873
new: 17.509775004326936
path: .spaces[0].metrics.halstead.level
old: 0.2857142857142857
new: 1.0
path: .spaces[0].metrics.nargs.sum
old: 1.0
new: 0.0
path: .spaces[0].metrics.nargs.average
old: 1.0
new: null
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: null
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 6.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].metrics.mi.mi_visual_studio
old: 74.61466703602454
new: 66.4817678441665
path: .spaces[0].metrics.mi.mi_original
old: 127.59108063160195
new: 113.6838230135247
path: .spaces[0].metrics.mi.mi_sei
old: 108.4759871562677
new: 112.4479469742697

### Code

    namespace mozilla {

    namespace dom {
    class PBrowserParent;
    class PBrowserChild;
    class PBrowserBridgeParent;
    }  // namespace dom

    class WidgetPointerEvent;
    }  // namespace mozilla