Global Metrics
path: .metrics.halstead.time
old: 1489.376488473169
new: 9173.493737450808
path: .metrics.halstead.length
old: 249.0
new: 1038.0
path: .metrics.halstead.level
old: 0.056140350877192984
new: 0.04827495736586646
path: .metrics.halstead.volume
old: 1505.0541357202549
new: 7971.300343286653
path: .metrics.halstead.N2
old: 95.0
new: 363.0
path: .metrics.halstead.difficulty
old: 17.8125
new: 20.714673913043477
path: .metrics.halstead.estimated_program_length
old: 343.1368500605771
new: 1476.5740657928443
path: .metrics.halstead.n2
old: 48.0
new: 184.0
path: .metrics.halstead.n1
old: 18.0
new: 21.0
path: .metrics.halstead.N1
old: 154.0
new: 675.0
path: .metrics.halstead.bugs
old: 0.29858185452651353
new: 1.003267925103294
path: .metrics.halstead.effort
old: 26808.77679251704
new: 165122.88727411456
path: .metrics.halstead.purity_ratio
old: 1.3780596387974984
new: 1.4225183678158422
path: .metrics.halstead.vocabulary
old: 66.0
new: 205.0
path: .metrics.nexits.sum
old: 1.0
new: 32.0
path: .metrics.nexits.average
old: 0.3333333333333333
new: 0.9411764705882352
path: .metrics.nom.functions
old: 3.0
new: 34.0
path: .metrics.nom.total
old: 3.0
new: 34.0
path: .metrics.cognitive.sum
old: 1.0
new: 2.0
path: .metrics.cognitive.average
old: 0.3333333333333333
new: 0.058823529411764705
path: .metrics.cyclomatic.sum
old: 5.0
new: 60.0
path: .metrics.cyclomatic.average
old: 1.25
new: 1.1320754716981132
path: .metrics.mi.mi_visual_studio
old: 38.4489215460427
new: 4.395509209355395
path: .metrics.mi.mi_original
old: 65.74765584373301
new: 7.5163207479977245
path: .metrics.mi.mi_sei
old: 48.10277464313059
new: -18.705534844742047
path: .metrics.nargs.sum
old: 5.0
new: 4.0
path: .metrics.nargs.average
old: 1.6666666666666667
new: 0.1176470588235294
path: .metrics.loc.sloc
old: 59.0
new: 576.0
path: .metrics.loc.cloc
old: 9.0
new: 207.0
path: .metrics.loc.ploc
old: 39.0
new: 280.0
path: .metrics.loc.blank
old: 11.0
new: 89.0
path: .metrics.loc.lloc
old: 17.0
new: 48.0
Spaces Data
Minimal test - lines (21, 574)
path: .spaces[1].metrics.halstead.bugs
old: 0.20823410225933453
new: 1.002169535784058
path: .spaces[1].metrics.halstead.purity_ratio
old: 1.5958133461442896
new: 1.3681583551689565
path: .spaces[1].metrics.halstead.level
old: 0.06397306397306397
new: 0.0474841494671523
path: .spaces[1].metrics.halstead.length
old: 172.0
new: 1027.0
path: .spaces[1].metrics.halstead.N1
old: 106.0
new: 674.0
path: .spaces[1].metrics.halstead.n2
old: 38.0
new: 176.0
path: .spaces[1].metrics.halstead.volume
old: 998.865046593908
new: 7827.847218581699
path: .spaces[1].metrics.halstead.difficulty
old: 15.63157894736842
new: 21.05965909090909
path: .spaces[1].metrics.halstead.vocabulary
old: 56.0
new: 197.0
path: .spaces[1].metrics.halstead.estimated_program_length
old: 274.4798955368178
new: 1405.0986307585183
path: .spaces[1].metrics.halstead.N2
old: 66.0
new: 353.0
path: .spaces[1].metrics.halstead.effort
old: 15613.837833599508
new: 164851.7938390515
path: .spaces[1].metrics.halstead.n1
old: 18.0
new: 21.0
path: .spaces[1].metrics.halstead.time
old: 867.4354351999726
new: 9158.432991058417
path: .spaces[1].metrics.mi.mi_sei
old: 63.54152232836664
new: -17.1360057905161
path: .spaces[1].metrics.mi.mi_original
old: 76.12870747381433
new: 8.701629457357342
path: .spaces[1].metrics.mi.mi_visual_studio
old: 44.519711972990834
new: 5.088672197284995
path: .spaces[1].metrics.cognitive.average
old: 1.0
new: 0.058823529411764705
path: .spaces[1].metrics.cognitive.sum
old: 1.0
new: 2.0
path: .spaces[1].metrics.loc.lloc
old: 12.0
new: 48.0
path: .spaces[1].metrics.loc.ploc
old: 25.0
new: 268.0
path: .spaces[1].metrics.loc.sloc
old: 37.0
new: 554.0
path: .spaces[1].metrics.loc.cloc
old: 6.0
new: 200.0
path: .spaces[1].metrics.loc.blank
old: 6.0
new: 86.0
path: .spaces[1].metrics.nexits.sum
old: 1.0
new: 32.0
path: .spaces[1].metrics.nexits.average
old: 1.0
new: 0.9411764705882352
path: .spaces[1].metrics.nom.functions
old: 1.0
new: 34.0
path: .spaces[1].metrics.nom.total
old: 1.0
new: 34.0
path: .spaces[1].metrics.nargs.average
old: 1.0
new: 0.1176470588235294
path: .spaces[1].metrics.nargs.sum
old: 1.0
new: 4.0
path: .spaces[1].metrics.cyclomatic.average
old: 2.0
new: 1.1372549019607845
path: .spaces[1].metrics.cyclomatic.sum
old: 2.0
new: 58.0
Code
namespace mozilla {
namespace widget {
class ModifierKeyState;
struct MSGResult;
class MouseScrollHandler {
public:
static MouseScrollHandler* GetInstance();
static void Initialize();
static void Shutdown();
static bool NeedsMessage(UINT aMsg);
static bool ProcessMessage(nsWindowBase* aWidget, UINT msg, WPARAM wParam,
LPARAM lParam, MSGResult& aResult);
/**
* See nsIWidget::SynthesizeNativeMouseScrollEvent() for the detail about
* this method.
*/
static nsresult SynthesizeNativeMouseScrollEvent(
nsWindowBase* aWidget, const LayoutDeviceIntPoint& aPoint,
uint32_t aNativeMessage, int32_t aDelta, uint32_t aModifierFlags,
uint32_t aAdditionalFlags);
/**
* IsWaitingInternalMessage() returns true if MouseScrollHandler posted
* an internal message for a native mouse wheel message and has not
* received it. Otherwise, false.
*/
static bool IsWaitingInternalMessage() {
return sInstance && sInstance->mIsWaitingInternalMessage;
}
private:
MouseScrollHandler();
~MouseScrollHandler();
bool mIsWaitingInternalMessage;
static void MaybeLogKeyState();
static MouseScrollHandler* sInstance;
/**
* InitEvent() initializes the aEvent. If aPoint is null, the result of
* GetCurrentMessagePos() will be used.
*/
static void InitEvent(nsWindowBase* aWidget, WidgetGUIEvent& aEvent,
LPARAM* aPoint);
/**
* GetModifierKeyState() returns current modifier key state.
* Note that some devices need some hack for the modifier key state.
* This method does it automatically.
*
* @param aMessage Handling message.
*/
static ModifierKeyState GetModifierKeyState(UINT aMessage);
/**
* MozGetMessagePos() returns the mouse cursor position when GetMessage()
* was called last time. However, if we're sending a native message,
* this returns the specified cursor position by
* SynthesizeNativeMouseScrollEvent().
*/
static POINTS GetCurrentMessagePos();
/**
* ProcessNativeMouseWheelMessage() processes WM_MOUSEWHEEL and
* WM_MOUSEHWHEEL. Additionally, processes WM_VSCROLL and WM_HSCROLL if they
* should be processed as mouse wheel message.
* This method posts MOZ_WM_MOUSEVWHEEL, MOZ_WM_MOUSEHWHEEL,
* MOZ_WM_VSCROLL or MOZ_WM_HSCROLL if we need to dispatch mouse scroll
* events. That avoids deadlock with plugin process.
*
* @param aWidget A window which receives the message.
* @param aMessage WM_MOUSEWHEEL, WM_MOUSEHWHEEL, WM_VSCROLL or
* WM_HSCROLL.
* @param aWParam The wParam value of the message.
* @param aLParam The lParam value of the message.
*/
void ProcessNativeMouseWheelMessage(nsWindowBase* aWidget, UINT aMessage,
WPARAM aWParam, LPARAM aLParam);
/**
* ProcessNativeScrollMessage() processes WM_VSCROLL and WM_HSCROLL.
* This method just call ProcessMouseWheelMessage() if the message should be
* processed as mouse wheel message. Otherwise, dispatches a content
* command event.
*
* @param aWidget A window which receives the message.
* @param aMessage WM_VSCROLL or WM_HSCROLL.
* @param aWParam The wParam value of the message.
* @param aLParam The lParam value of the message.
* @return TRUE if the message is processed. Otherwise, FALSE.
*/
bool ProcessNativeScrollMessage(nsWindowBase* aWidget, UINT aMessage,
WPARAM aWParam, LPARAM aLParam);
/**
* HandleMouseWheelMessage() processes MOZ_WM_MOUSEVWHEEL and
* MOZ_WM_MOUSEHWHEEL which are posted when one of our windows received
* WM_MOUSEWHEEL or WM_MOUSEHWHEEL for avoiding deadlock with OOPP.
*
* @param aWidget A window which receives the wheel message.
* @param aMessage MOZ_WM_MOUSEWHEEL or MOZ_WM_MOUSEHWHEEL.
* @param aWParam The wParam value of the original message.
* @param aLParam The lParam value of the original message.
*/
void HandleMouseWheelMessage(nsWindowBase* aWidget, UINT aMessage,
WPARAM aWParam, LPARAM aLParam);
/**
* HandleScrollMessageAsMouseWheelMessage() processes the MOZ_WM_VSCROLL and
* MOZ_WM_HSCROLL which are posted when one of mouse windows received
* WM_VSCROLL or WM_HSCROLL and user wants them to emulate mouse wheel
* message's behavior.
*
* @param aWidget A window which receives the scroll message.
* @param aMessage MOZ_WM_VSCROLL or MOZ_WM_HSCROLL.
* @param aWParam The wParam value of the original message.
* @param aLParam The lParam value of the original message.
*/
void HandleScrollMessageAsMouseWheelMessage(nsWindowBase* aWidget,
UINT aMessage, WPARAM aWParam,
LPARAM aLParam);
/**
* ComputeMessagePos() computes the cursor position when the message was
* added to the queue.
*
* @param aMessage Handling message.
* @param aWParam Handling message's wParam.
* @param aLParam Handling message's lParam.
* @return Mouse cursor position when the message is added to
* the queue or current cursor position if the result of
* ::GetMessagePos() is broken.
*/
POINT ComputeMessagePos(UINT aMessage, WPARAM aWParam, LPARAM aLParam);
class EventInfo {
public:
/**
* @param aWidget An nsWindow which is handling the event.
* @param aMessage Must be WM_MOUSEWHEEL or WM_MOUSEHWHEEL.
*/
EventInfo(nsWindowBase* aWidget, UINT aMessage, WPARAM aWParam,
LPARAM aLParam);
bool CanDispatchWheelEvent() const;
int32_t GetNativeDelta() const { return mDelta; }
HWND GetWindowHandle() const { return mWnd; }
const TimeStamp& GetTimeStamp() const { return mTimeStamp; }
bool IsVertical() const { return mIsVertical; }
bool IsPositive() const { return (mDelta > 0); }
bool IsPage() const { return mIsPage; }
/**
* @return Number of lines or pages scrolled per WHEEL_DELTA.
*/
int32_t GetScrollAmount() const;
protected:
EventInfo()
: mIsVertical(false), mIsPage(false), mDelta(0), mWnd(nullptr) {}
// TRUE if event is for vertical scroll. Otherwise, FALSE.
bool mIsVertical;
// TRUE if event scrolls per page, otherwise, FALSE.
bool mIsPage;
// The native delta value.
int32_t mDelta;
// The window handle which is handling the event.
HWND mWnd;
// Timestamp of the event.
TimeStamp mTimeStamp;
};
class LastEventInfo : public EventInfo {
public:
LastEventInfo() : EventInfo(), mAccumulatedDelta(0) {}
/**
* CanContinueTransaction() checks whether the new event can continue the
* last transaction or not. Note that if there is no transaction, this
* returns true.
*/
bool CanContinueTransaction(const EventInfo& aNewEvent);
/**
* ResetTransaction() resets the transaction, i.e., the instance forgets
* the last event information.
*/
void ResetTransaction();
/**
* RecordEvent() saves the information of new event.
*/
void RecordEvent(const EventInfo& aEvent);
/**
* InitWheelEvent() initializes NS_WHEEL_WHEEL event and
* recomputes the remaning detla for the event.
* This must be called only once during handling a message and after
* RecordEvent() is called.
*
* @param aWidget A window which will dispatch the event.
* @param aWheelEvent An NS_WHEEL_WHEEL event, this will be
* initialized.
* @param aModKeyState Current modifier key state.
* @return TRUE if the event is ready to dispatch.
* Otherwise, FALSE.
*/
bool InitWheelEvent(nsWindowBase* aWidget, WidgetWheelEvent& aWheelEvent,
const ModifierKeyState& aModKeyState, LPARAM aLParam);
private:
static int32_t RoundDelta(double aDelta);
int32_t mAccumulatedDelta;
};
LastEventInfo mLastEventInfo;
class SystemSettings {
public:
SystemSettings() : mInitialized(false) {}
void Init();
void MarkDirty();
void NotifyUserPrefsMayOverrideSystemSettings();
// On some environments, SystemParametersInfo() may be hooked by touchpad
// utility or something. In such case, when user changes active pointing
// device to another one, the result of SystemParametersInfo() may be
// changed without WM_SETTINGCHANGE message. For avoiding this trouble,
// we need to modify cache of system settings at every wheel message
// handling if we meet known device whose utility may hook the API.
void TrustedScrollSettingsDriver();
// Returns true if the system scroll may be overridden for faster scroll.
// Otherwise, false. For example, if the user maybe uses an expensive
// mouse which supports acceleration of scroll speed, faster scroll makes
// the user inconvenient.
bool IsOverridingSystemScrollSpeedAllowed();
int32_t GetScrollAmount(bool aForVertical) const {
MOZ_ASSERT(mInitialized, "SystemSettings must be initialized");
return aForVertical ? mScrollLines : mScrollChars;
}
bool IsPageScroll(bool aForVertical) const {
MOZ_ASSERT(mInitialized, "SystemSettings must be initialized");
return aForVertical ? (uint32_t(mScrollLines) == WHEEL_PAGESCROLL)
: (uint32_t(mScrollChars) == WHEEL_PAGESCROLL);
}
// The default vertical and horizontal scrolling speed is 3, this is defined
// on the document of SystemParametersInfo in MSDN.
static int32_t DefaultScrollLines() { return 3; }
static int32_t DefaultScrollChars() { return 3; }
private:
bool mInitialized;
// The result of SystemParametersInfo() may not be reliable since it may
// be hooked. So, if the values are initialized with prefs, we can trust
// the value. Following mIsReliableScroll* are set true when mScroll* are
// initialized with prefs.
bool mIsReliableScrollLines;
bool mIsReliableScrollChars;
int32_t mScrollLines;
int32_t mScrollChars;
// Returns true if cached value is changed.
bool InitScrollLines();
bool InitScrollChars();
void RefreshCache();
};
SystemSettings mSystemSettings;
class UserPrefs {
public:
UserPrefs();
~UserPrefs();
void MarkDirty();
bool IsScrollMessageHandledAsWheelMessage() {
Init();
return mScrollMessageHandledAsWheelMessage;
}
bool IsSystemSettingCacheEnabled() {
Init();
return mEnableSystemSettingCache;
}
bool IsSystemSettingCacheForciblyEnabled() {
Init();
return mForceEnableSystemSettingCache;
}
bool ShouldEmulateToMakeWindowUnderCursorForeground() {
Init();
return mEmulateToMakeWindowUnderCursorForeground;
}
int32_t GetOverriddenVerticalScrollAmout() {
Init();
return mOverriddenVerticalScrollAmount;
}
int32_t GetOverriddenHorizontalScrollAmout() {
Init();
return mOverriddenHorizontalScrollAmount;
}
int32_t GetMouseScrollTransactionTimeout() {
Init();
return mMouseScrollTransactionTimeout;
}
private:
void Init();
static void OnChange(const char* aPrefName, void* aSelf) {
static_cast(aSelf)->MarkDirty();
}
bool mInitialized;
bool mScrollMessageHandledAsWheelMessage;
bool mEnableSystemSettingCache;
bool mForceEnableSystemSettingCache;
bool mEmulateToMakeWindowUnderCursorForeground;
int32_t mOverriddenVerticalScrollAmount;
int32_t mOverriddenHorizontalScrollAmount;
int32_t mMouseScrollTransactionTimeout;
};
UserPrefs mUserPrefs;
class SynthesizingEvent {
public:
SynthesizingEvent()
: mWnd(nullptr),
mMessage(0),
mWParam(0),
mLParam(0),
mStatus(NOT_SYNTHESIZING) {}
~SynthesizingEvent() {}
static bool IsSynthesizing();
nsresult Synthesize(const POINTS& aCursorPoint, HWND aWnd, UINT aMessage,
WPARAM aWParam, LPARAM aLParam,
const BYTE (&aKeyStates)[256]);
void NativeMessageReceived(nsWindowBase* aWidget, UINT aMessage,
WPARAM aWParam, LPARAM aLParam);
void NotifyNativeMessageHandlingFinished();
void NotifyInternalMessageHandlingFinished();
const POINTS& GetCursorPoint() const { return mCursorPoint; }
private:
POINTS mCursorPoint;
HWND mWnd;
UINT mMessage;
WPARAM mWParam;
LPARAM mLParam;
BYTE mKeyState[256];
BYTE mOriginalKeyState[256];
enum Status {
NOT_SYNTHESIZING,
SENDING_MESSAGE,
NATIVE_MESSAGE_RECEIVED,
INTERNAL_MESSAGE_POSTED,
};
Status mStatus;
const char* GetStatusName() {
switch (mStatus) {
case NOT_SYNTHESIZING:
return "NOT_SYNTHESIZING";
case SENDING_MESSAGE:
return "SENDING_MESSAGE";
case NATIVE_MESSAGE_RECEIVED:
return "NATIVE_MESSAGE_RECEIVED";
case INTERNAL_MESSAGE_POSTED:
return "INTERNAL_MESSAGE_POSTED";
default:
return "Unknown";
}
}
void Finish();
}; // SynthesizingEvent
SynthesizingEvent* mSynthesizingEvent;
public:
class Device {
public:
// SynTP is a touchpad driver of Synaptics.
class SynTP {
public:
static bool IsDriverInstalled() { return sMajorVersion != 0; }
/**
* GetDriverMajorVersion() returns the installed driver's major version.
* If SynTP driver isn't installed, this returns 0.
*/
static int32_t GetDriverMajorVersion() { return sMajorVersion; }
/**
* GetDriverMinorVersion() returns the installed driver's minor version.
* If SynTP driver isn't installed, this returns -1.
*/
static int32_t GetDriverMinorVersion() { return sMinorVersion; }
static void Init();
private:
static bool sInitialized;
static int32_t sMajorVersion;
static int32_t sMinorVersion;
};
class Elantech {
public:
/**
* GetDriverMajorVersion() returns the installed driver's major version.
* If Elantech's driver was installed, returns 0.
*/
static int32_t GetDriverMajorVersion();
/**
* IsHelperWindow() checks whether aWnd is a helper window of Elantech's
* touchpad. Returns TRUE if so. Otherwise, FALSE.
*/
static bool IsHelperWindow(HWND aWnd);
/**
* Key message handler for Elantech's hack. Returns TRUE if the message
* is consumed by this handler. Otherwise, FALSE.
*/
static bool HandleKeyMessage(nsWindowBase* aWidget, UINT aMsg,
WPARAM aWParam, LPARAM aLParam);
static void UpdateZoomUntil();
static bool IsZooming();
static void Init();
static bool IsPinchHackNeeded() { return sUsePinchHack; }
private:
// Whether to enable the Elantech swipe gesture hack.
static bool sUseSwipeHack;
// Whether to enable the Elantech pinch-to-zoom gesture hack.
static bool sUsePinchHack;
static DWORD sZoomUntil;
}; // class Elantech
// Apoint is a touchpad driver of Alps.
class Apoint {
public:
static bool IsDriverInstalled() { return sMajorVersion != 0; }
/**
* GetDriverMajorVersion() returns the installed driver's major version.
* If Apoint driver isn't installed, this returns 0.
*/
static int32_t GetDriverMajorVersion() { return sMajorVersion; }
/**
* GetDriverMinorVersion() returns the installed driver's minor version.
* If Apoint driver isn't installed, this returns -1.
*/
static int32_t GetDriverMinorVersion() { return sMinorVersion; }
static void Init();
private:
static bool sInitialized;
static int32_t sMajorVersion;
static int32_t sMinorVersion;
};
class TrackPoint {
public:
/**
* IsDriverInstalled() returns TRUE if TrackPoint's driver is installed.
* Otherwise, returns FALSE.
*/
static bool IsDriverInstalled();
}; // class TrackPoint
class UltraNav {
public:
/**
* IsObsoleteDriverInstalled() checks whether obsoleted UltraNav
* is installed on the environment.
* Returns TRUE if it was installed. Otherwise, FALSE.
*/
static bool IsObsoleteDriverInstalled();
}; // class UltraNav
class SetPoint {
public:
/**
* SetPoint, Logitech's mouse driver, may report wrong cursor position
* for WM_MOUSEHWHEEL message. See comment in the implementation for
* the detail.
*/
static bool IsGetMessagePosResponseValid(UINT aMessage, WPARAM aWParam,
LPARAM aLParam);
private:
static bool sMightBeUsing;
};
static void Init();
static bool IsFakeScrollableWindowNeeded() {
return sFakeScrollableWindowNeeded;
}
private:
/**
* Gets the bool value of aPrefName used to enable or disable an input
* workaround (like the Trackpoint hack). The pref can take values 0 (for
* disabled), 1 (for enabled) or -1 (to automatically detect whether to
* enable the workaround).
*
* @param aPrefName The name of the pref.
* @param aValueIfAutomatic Whether the given input workaround should be
* enabled by default.
*/
static bool GetWorkaroundPref(const char* aPrefName,
bool aValueIfAutomatic);
static bool sFakeScrollableWindowNeeded;
}; // class Device
};
} // namespace widget
} // namespace mozilla
Minimal test - lines (19, 19)
path: .spaces[0].metrics.loc.lloc
old: 1.0
new: 0.0
path: .spaces[0].metrics.loc.sloc
old: 3.0
new: 1.0
path: .spaces[0].metrics.loc.ploc
old: 3.0
new: 1.0
path: .spaces[0].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].metrics.nargs.average
old: 3.0
new: null
path: .spaces[0].metrics.nargs.sum
old: 3.0
new: 0.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].metrics.mi.mi_sei
old: 113.6936022941664
new: null
path: .spaces[0].metrics.mi.mi_original
old: 131.2076558536833
new: null
path: .spaces[0].metrics.mi.mi_visual_studio
old: 76.72962330624755
new: null
path: .spaces[0].metrics.halstead.difficulty
old: 2.9166666666666665
new: 0.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 27.11941547876375
new: null
path: .spaces[0].metrics.halstead.N1
old: 12.0
new: 0.0
path: .spaces[0].metrics.halstead.n2
old: 6.0
new: 1.0
path: .spaces[0].metrics.halstead.vocabulary
old: 11.0
new: 1.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.4273376567770395
new: null
path: .spaces[0].metrics.halstead.effort
old: 191.7101688661502
new: 0.0
path: .spaces[0].metrics.halstead.length
old: 19.0
new: 1.0
path: .spaces[0].metrics.halstead.time
old: 10.650564937008346
new: 0.0
path: .spaces[0].metrics.halstead.volume
old: 65.72920075410865
new: 0.0
path: .spaces[0].metrics.halstead.n1
old: 5.0
new: 0.0
path: .spaces[0].metrics.halstead.level
old: 0.34285714285714286
new: null
path: .spaces[0].metrics.halstead.N2
old: 7.0
new: 1.0
path: .spaces[0].metrics.halstead.bugs
old: 0.011082613263103974
new: 0.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: null
Code
class nsWindowBase;