Global Metrics

path: .metrics.nexits.sum
old: 0.0
new: 2.0

path: .metrics.nexits.average
old: 0.0
new: 0.3333333333333333

path: .metrics.nargs.average
old: 1.5714285714285714
new: 1.0

path: .metrics.nargs.sum
old: 11.0
new: 6.0

path: .metrics.cognitive.average
old: 0.2857142857142857
new: 0.3333333333333333

path: .metrics.nom.total
old: 7.0
new: 6.0

path: .metrics.nom.functions
old: 7.0
new: 6.0

path: .metrics.cyclomatic.sum
old: 11.0
new: 15.0

path: .metrics.cyclomatic.average
old: 1.1
new: 1.1538461538461535

path: .metrics.mi.mi_sei
old: 44.84405577072875
new: 19.953664502806355

path: .metrics.mi.mi_original
old: 57.14199831306664
new: 38.173241749220864

path: .metrics.mi.mi_visual_studio
old: 33.41637328249511
new: 22.32353318667887

path: .metrics.halstead.n2
old: 59.0
new: 97.0

path: .metrics.halstead.time
old: 1350.5561070242966
new: 3503.7679594837637

path: .metrics.halstead.length
old: 261.0
new: 443.0

path: .metrics.halstead.volume
old: 1620.667328429156
new: 3043.5715707754484

path: .metrics.halstead.N1
old: 143.0
new: 242.0

path: .metrics.halstead.estimated_program_length
old: 405.6792988464764
new: 726.6301075898987

path: .metrics.halstead.purity_ratio
old: 1.554326815503741
new: 1.640248549864331

path: .metrics.halstead.bugs
old: 0.27972771821190956
new: 0.5281419199813144

path: .metrics.halstead.vocabulary
old: 74.0
new: 117.0

path: .metrics.halstead.difficulty
old: 15.0
new: 20.721649484536083

path: .metrics.halstead.n1
old: 15.0
new: 20.0

path: .metrics.halstead.N2
old: 118.0
new: 201.0

path: .metrics.halstead.level
old: 0.06666666666666667
new: 0.04825870646766169

path: .metrics.halstead.effort
old: 24310.00992643734
new: 63067.82327070775

path: .metrics.loc.lloc
old: 16.0
new: 19.0

path: .metrics.loc.cloc
old: 26.0
new: 75.0

path: .metrics.loc.ploc
old: 50.0
new: 111.0

path: .metrics.loc.blank
old: 14.0
new: 38.0

path: .metrics.loc.sloc
old: 90.0
new: 224.0

Spaces Data

Minimal test - lines (129, 135)

path: .spaces[0].spaces[0].spaces[3].metrics.nargs.average
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.nargs.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.cognitive.average
old: 0.0
new: 2.0

path: .spaces[0].spaces[0].spaces[3].metrics.cognitive.sum
old: 0.0
new: 2.0

path: .spaces[0].spaces[0].spaces[3].metrics.cyclomatic.average
old: 1.0
new: 3.0

path: .spaces[0].spaces[0].spaces[3].metrics.cyclomatic.sum
old: 1.0
new: 3.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.bugs
old: 0.009388882548620756
new: 0.024104229172388934

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.estimated_program_length
old: 23.509775004326936
new: 71.27302875388389

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.N1
old: 7.0
new: 17.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.difficulty
old: 3.75
new: 5.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.purity_ratio
old: 1.9591479170272448
new: 2.5454653126387106

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.time
old: 8.304820237218406
new: 34.16246884383481

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.n2
old: 4.0
new: 11.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.vocabulary
old: 10.0
new: 21.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.volume
old: 39.86313713864835
new: 122.9848878378053

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.level
old: 0.26666666666666666
new: 0.2

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.N2
old: 5.0
new: 11.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.effort
old: 149.4867642699313
new: 614.9244391890265

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.n1
old: 6.0
new: 10.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.length
old: 12.0
new: 28.0

path: .spaces[0].spaces[0].spaces[3].metrics.mi.mi_original
old: 133.808130442365
new: 113.76353586477629

path: .spaces[0].spaces[0].spaces[3].metrics.mi.mi_visual_studio
old: 78.25036867974562
new: 66.5283835466528

path: .spaces[0].spaces[0].spaces[3].metrics.mi.mi_sei
old: 156.43782660646212
new: 88.73069661230713

path: .spaces[0].spaces[0].spaces[3].metrics.loc.lloc
old: 1.0
new: 4.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.sloc
old: 3.0
new: 7.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.cloc
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.ploc
old: 3.0
new: 7.0

Code

  void MaybeResolveShutdown() {
    mQueueMonitor.AssertCurrentThreadOwns();
    if (mIsShutdown && !mIsRunning) {
      mShutdownPromise.ResolveIfExists(true, __func__);
      mTarget = nullptr;
    }
  }

Minimal test - lines (50, 220)

path: .spaces[0].spaces[0].metrics.loc.sloc
old: 72.0
new: 171.0

path: .spaces[0].spaces[0].metrics.loc.cloc
old: 18.0
new: 43.0

path: .spaces[0].spaces[0].metrics.loc.blank
old: 13.0
new: 32.0

path: .spaces[0].spaces[0].metrics.loc.lloc
old: 16.0
new: 19.0

path: .spaces[0].spaces[0].metrics.loc.ploc
old: 41.0
new: 96.0

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 48.88666839521784
new: 23.277999883061852

path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 35.954374463323596
new: 25.37610653117938

path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 61.48198033228334
new: 43.39314216831674

path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.2857142857142857
new: 0.3333333333333333

path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.125
new: 1.181818181818182

path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 9.0
new: 13.0

path: .spaces[0].spaces[0].metrics.nom.total
old: 7.0
new: 6.0

path: .spaces[0].spaces[0].metrics.nom.functions
old: 7.0
new: 6.0

path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.2788189088537787
new: 0.5190321674676801

path: .spaces[0].spaces[0].metrics.halstead.N2
old: 111.0
new: 187.0

path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 15.70754716981132
new: 21.74418604651163

path: .spaces[0].spaces[0].metrics.halstead.effort
old: 24191.634760023575
new: 61443.12470946438

path: .spaces[0].spaces[0].metrics.halstead.length
old: 253.0
new: 420.0

path: .spaces[0].spaces[0].metrics.halstead.n1
old: 15.0
new: 20.0

path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.431553925003863
new: 1.5216603114336371

path: .spaces[0].spaces[0].metrics.halstead.N1
old: 142.0
new: 233.0

path: .spaces[0].spaces[0].metrics.halstead.time
old: 1343.9797088901987
new: 3413.5069283035764

path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 68.0
new: 106.0

path: .spaces[0].spaces[0].metrics.halstead.n2
old: 53.0
new: 86.0

path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.06366366366366366
new: 0.045989304812834225

path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 362.1831430259773
new: 639.0973308021277

path: .spaces[0].spaces[0].metrics.halstead.volume
old: 1540.1280988363358
new: 2825.7265909165435

path: .spaces[0].spaces[0].metrics.nargs.sum
old: 11.0
new: 6.0

path: .spaces[0].spaces[0].metrics.nargs.average
old: 1.5714285714285714
new: 1.0

path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: 0.3333333333333333

path: .spaces[0].spaces[0].metrics.nexits.sum
old: 0.0
new: 2.0

Code

class TaskQueue : public AbstractThread, public nsIDirectTaskDispatcher {
  class EventTargetWrapper;

 public:
  explicit TaskQueue(already_AddRefed aTarget,
                     bool aSupportsTailDispatch = false);

  TaskQueue(already_AddRefed aTarget, const char* aName,
            bool aSupportsTailDispatch = false);

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIDIRECTTASKDISPATCHER

  TaskDispatcher& TailDispatcher() override;

  NS_IMETHOD Dispatch(already_AddRefed aEvent,
                      uint32_t aFlags) override {
    nsCOMPtr runnable = aEvent;
    {
      MonitorAutoLock mon(mQueueMonitor);
      return DispatchLocked(/* passed by ref */ runnable, aFlags,
                            NormalDispatch);
    }
    // If the ownership of |r| is not transferred in DispatchLocked() due to
    // dispatch failure, it will be deleted here outside the lock. We do so
    // since the destructor of the runnable might access TaskQueue and result
    // in deadlocks.
  }

  [[nodiscard]] nsresult Dispatch(
      already_AddRefed aRunnable,
      DispatchReason aReason = NormalDispatch) override {
    nsCOMPtr r = aRunnable;
    {
      MonitorAutoLock mon(mQueueMonitor);
      return DispatchLocked(/* passed by ref */ r, NS_DISPATCH_NORMAL, aReason);
    }
    // If the ownership of |r| is not transferred in DispatchLocked() due to
    // dispatch failure, it will be deleted here outside the lock. We do so
    // since the destructor of the runnable might access TaskQueue and result
    // in deadlocks.
  }

  // So we can access nsIEventTarget::Dispatch(nsIRunnable*, uint32_t aFlags)
  using nsIEventTarget::Dispatch;

  // Puts the queue in a shutdown state and returns immediately. The queue will
  // remain alive at least until all the events are drained, because the Runners
  // hold a strong reference to the task queue, and one of them is always held
  // by the target event queue when the task queue is non-empty.
  //
  // The returned promise is resolved when the queue goes empty.
  RefPtr BeginShutdown();

  // Blocks until all task finish executing.
  void AwaitIdle();

  // Blocks until the queue is flagged for shutdown and all tasks have finished
  // executing.
  void AwaitShutdownAndIdle();

  bool IsEmpty();

  // Returns true if the current thread is currently running a Runnable in
  // the task queue.
  bool IsCurrentThreadIn() const override;
  using nsISerialEventTarget::IsOnCurrentThread;

 protected:
  virtual ~TaskQueue();

  // Blocks until all task finish executing. Called internally by methods
  // that need to wait until the task queue is idle.
  // mQueueMonitor must be held.
  void AwaitIdleLocked();

  nsresult DispatchLocked(nsCOMPtr& aRunnable, uint32_t aFlags,
                          DispatchReason aReason = NormalDispatch);

  void MaybeResolveShutdown() {
    mQueueMonitor.AssertCurrentThreadOwns();
    if (mIsShutdown && !mIsRunning) {
      mShutdownPromise.ResolveIfExists(true, __func__);
      mTarget = nullptr;
    }
  }

  nsCOMPtr mTarget;

  // Monitor that protects the queue and mIsRunning;
  Monitor mQueueMonitor;

  typedef struct TaskStruct {
    nsCOMPtr event;
    uint32_t flags;
  } TaskStruct;

  // Queue of tasks to run.
  std::queue mTasks;

  // The thread currently running the task queue. We store a reference
  // to this so that IsCurrentThreadIn() can tell if the current thread
  // is the thread currently running in the task queue.
  //
  // This may be read on any thread, but may only be written on mRunningThread.
  // The thread can't die while we're running in it, and we only use it for
  // pointer-comparison with the current thread anyway - so we make it atomic
  // and don't refcount it.
  Atomic mRunningThread;

  // RAII class that gets instantiated for each dispatched task.
  class AutoTaskGuard {
   public:
    explicit AutoTaskGuard(TaskQueue* aQueue)
        : mQueue(aQueue), mLastCurrentThread(nullptr) {
      // NB: We don't hold the lock to aQueue here. Don't do anything that
      // might require it.
      MOZ_ASSERT(!mQueue->mTailDispatcher);
      mTaskDispatcher.emplace(aQueue,
                              /* aIsTailDispatcher = */ true);
      mQueue->mTailDispatcher = mTaskDispatcher.ptr();

      mLastCurrentThread = sCurrentThreadTLS.get();
      sCurrentThreadTLS.set(aQueue);

      MOZ_ASSERT(mQueue->mRunningThread == nullptr);
      mQueue->mRunningThread = PR_GetCurrentThread();
    }

    ~AutoTaskGuard() {
      mTaskDispatcher->DrainDirectTasks();
      mTaskDispatcher.reset();

      MOZ_ASSERT(mQueue->mRunningThread == PR_GetCurrentThread());
      mQueue->mRunningThread = nullptr;

      sCurrentThreadTLS.set(mLastCurrentThread);
      mQueue->mTailDispatcher = nullptr;
    }

   private:
    Maybe mTaskDispatcher;
    TaskQueue* mQueue;
    AbstractThread* mLastCurrentThread;
  };

  TaskDispatcher* mTailDispatcher;

  // True if we've dispatched an event to the target to execute events from
  // the queue.
  bool mIsRunning;

  // True if we've started our shutdown process.
  bool mIsShutdown;
  MozPromiseHolder mShutdownPromise;

  // The name of this TaskQueue. Useful when debugging dispatch failures.
  const char* const mName;

  SimpleTaskQueue mDirectTasks;

  class Runner : public Runnable {
   public:
    explicit Runner(TaskQueue* aQueue)
        : Runnable("TaskQueue::Runner"), mQueue(aQueue) {}
    NS_IMETHOD Run() override;

   private:
    RefPtr mQueue;
  };
};

Minimal test - lines (21, 222)

path: .spaces[0].metrics.nargs.average
old: 1.5714285714285714
new: 1.0

path: .spaces[0].metrics.nargs.sum
old: 11.0
new: 6.0

path: .spaces[0].metrics.halstead.n2
old: 54.0
new: 88.0

path: .spaces[0].metrics.halstead.N2
old: 112.0
new: 191.0

path: .spaces[0].metrics.halstead.volume
old: 1557.673736478433
new: 2924.866288436782

path: .spaces[0].metrics.halstead.bugs
old: 0.27911730365696885
new: 0.5304566357830517

path: .spaces[0].metrics.halstead.n1
old: 15.0
new: 20.0

path: .spaces[0].metrics.halstead.difficulty
old: 15.555555555555555
new: 21.704545454545453

path: .spaces[0].metrics.halstead.effort
old: 24230.48034522007
new: 63482.89330584378

path: .spaces[0].metrics.halstead.vocabulary
old: 69.0
new: 108.0

path: .spaces[0].metrics.halstead.time
old: 1346.1377969566704
new: 3526.8274058802103

path: .spaces[0].metrics.halstead.purity_ratio
old: 1.448499153141
new: 1.5123984857686592

path: .spaces[0].metrics.halstead.estimated_program_length
old: 369.36728405095505
new: 654.8685443378295

path: .spaces[0].metrics.halstead.length
old: 255.0
new: 433.0

path: .spaces[0].metrics.halstead.level
old: 0.0642857142857143
new: 0.04607329842931938

path: .spaces[0].metrics.halstead.N1
old: 143.0
new: 242.0

path: .spaces[0].metrics.cyclomatic.average
old: 1.1111111111111112
new: 1.1666666666666667

path: .spaces[0].metrics.cyclomatic.sum
old: 10.0
new: 14.0

path: .spaces[0].metrics.loc.blank
old: 12.0
new: 35.0

path: .spaces[0].metrics.loc.ploc
old: 43.0
new: 99.0

path: .spaces[0].metrics.loc.sloc
old: 74.0
new: 202.0

path: .spaces[0].metrics.loc.cloc
old: 19.0
new: 68.0

path: .spaces[0].metrics.loc.lloc
old: 16.0
new: 19.0

path: .spaces[0].metrics.cognitive.average
old: 0.2857142857142857
new: 0.3333333333333333

path: .spaces[0].metrics.nexits.average
old: 0.0
new: 0.3333333333333333

path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 2.0

path: .spaces[0].metrics.nom.total
old: 7.0
new: 6.0

path: .spaces[0].metrics.nom.functions
old: 7.0
new: 6.0

path: .spaces[0].metrics.mi.mi_sei
old: 48.300994327796566
new: 22.973762892370672

path: .spaces[0].metrics.mi.mi_original
old: 60.74921176783758
new: 40.28484226671664

path: .spaces[0].metrics.mi.mi_visual_studio
old: 35.525854834992735
new: 23.558387290477565

Code

namespace mozilla {

typedef MozPromise ShutdownPromise;

// Abstracts executing runnables in order on an arbitrary event target. The
// runnables dispatched to the TaskQueue will be executed in the order in which
// they're received, and are guaranteed to not be executed concurrently.
// They may be executed on different threads, and a memory barrier is used
// to make this threadsafe for objects that aren't already threadsafe.
//
// Note, since a TaskQueue can also be converted to an nsIEventTarget using
// WrapAsEventTarget() its possible to construct a hierarchy of TaskQueues.
// Consider these three TaskQueues:
//
//  TQ1 dispatches to the main thread
//  TQ2 dispatches to TQ1
//  TQ3 dispatches to TQ1
//
// This ensures there is only ever a single runnable from the entire chain on
// the main thread.  It also ensures that TQ2 and TQ3 only have a single
// runnable in TQ1 at any time.
//
// This arrangement lets you prioritize work by dispatching runnables directly
// to TQ1.  You can issue many runnables for important work.  Meanwhile the TQ2
// and TQ3 work will always execute at most one runnable and then yield.
//
// A TaskQueue does not require explicit shutdown, however it provides a
// BeginShutdown() method that places TaskQueue in a shut down state and returns
// a promise that gets resolved once all pending tasks have completed
class TaskQueue : public AbstractThread, public nsIDirectTaskDispatcher {
  class EventTargetWrapper;

 public:
  explicit TaskQueue(already_AddRefed aTarget,
                     bool aSupportsTailDispatch = false);

  TaskQueue(already_AddRefed aTarget, const char* aName,
            bool aSupportsTailDispatch = false);

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_NSIDIRECTTASKDISPATCHER

  TaskDispatcher& TailDispatcher() override;

  NS_IMETHOD Dispatch(already_AddRefed aEvent,
                      uint32_t aFlags) override {
    nsCOMPtr runnable = aEvent;
    {
      MonitorAutoLock mon(mQueueMonitor);
      return DispatchLocked(/* passed by ref */ runnable, aFlags,
                            NormalDispatch);
    }
    // If the ownership of |r| is not transferred in DispatchLocked() due to
    // dispatch failure, it will be deleted here outside the lock. We do so
    // since the destructor of the runnable might access TaskQueue and result
    // in deadlocks.
  }

  [[nodiscard]] nsresult Dispatch(
      already_AddRefed aRunnable,
      DispatchReason aReason = NormalDispatch) override {
    nsCOMPtr r = aRunnable;
    {
      MonitorAutoLock mon(mQueueMonitor);
      return DispatchLocked(/* passed by ref */ r, NS_DISPATCH_NORMAL, aReason);
    }
    // If the ownership of |r| is not transferred in DispatchLocked() due to
    // dispatch failure, it will be deleted here outside the lock. We do so
    // since the destructor of the runnable might access TaskQueue and result
    // in deadlocks.
  }

  // So we can access nsIEventTarget::Dispatch(nsIRunnable*, uint32_t aFlags)
  using nsIEventTarget::Dispatch;

  // Puts the queue in a shutdown state and returns immediately. The queue will
  // remain alive at least until all the events are drained, because the Runners
  // hold a strong reference to the task queue, and one of them is always held
  // by the target event queue when the task queue is non-empty.
  //
  // The returned promise is resolved when the queue goes empty.
  RefPtr BeginShutdown();

  // Blocks until all task finish executing.
  void AwaitIdle();

  // Blocks until the queue is flagged for shutdown and all tasks have finished
  // executing.
  void AwaitShutdownAndIdle();

  bool IsEmpty();

  // Returns true if the current thread is currently running a Runnable in
  // the task queue.
  bool IsCurrentThreadIn() const override;
  using nsISerialEventTarget::IsOnCurrentThread;

 protected:
  virtual ~TaskQueue();

  // Blocks until all task finish executing. Called internally by methods
  // that need to wait until the task queue is idle.
  // mQueueMonitor must be held.
  void AwaitIdleLocked();

  nsresult DispatchLocked(nsCOMPtr& aRunnable, uint32_t aFlags,
                          DispatchReason aReason = NormalDispatch);

  void MaybeResolveShutdown() {
    mQueueMonitor.AssertCurrentThreadOwns();
    if (mIsShutdown && !mIsRunning) {
      mShutdownPromise.ResolveIfExists(true, __func__);
      mTarget = nullptr;
    }
  }

  nsCOMPtr mTarget;

  // Monitor that protects the queue and mIsRunning;
  Monitor mQueueMonitor;

  typedef struct TaskStruct {
    nsCOMPtr event;
    uint32_t flags;
  } TaskStruct;

  // Queue of tasks to run.
  std::queue mTasks;

  // The thread currently running the task queue. We store a reference
  // to this so that IsCurrentThreadIn() can tell if the current thread
  // is the thread currently running in the task queue.
  //
  // This may be read on any thread, but may only be written on mRunningThread.
  // The thread can't die while we're running in it, and we only use it for
  // pointer-comparison with the current thread anyway - so we make it atomic
  // and don't refcount it.
  Atomic mRunningThread;

  // RAII class that gets instantiated for each dispatched task.
  class AutoTaskGuard {
   public:
    explicit AutoTaskGuard(TaskQueue* aQueue)
        : mQueue(aQueue), mLastCurrentThread(nullptr) {
      // NB: We don't hold the lock to aQueue here. Don't do anything that
      // might require it.
      MOZ_ASSERT(!mQueue->mTailDispatcher);
      mTaskDispatcher.emplace(aQueue,
                              /* aIsTailDispatcher = */ true);
      mQueue->mTailDispatcher = mTaskDispatcher.ptr();

      mLastCurrentThread = sCurrentThreadTLS.get();
      sCurrentThreadTLS.set(aQueue);

      MOZ_ASSERT(mQueue->mRunningThread == nullptr);
      mQueue->mRunningThread = PR_GetCurrentThread();
    }

    ~AutoTaskGuard() {
      mTaskDispatcher->DrainDirectTasks();
      mTaskDispatcher.reset();

      MOZ_ASSERT(mQueue->mRunningThread == PR_GetCurrentThread());
      mQueue->mRunningThread = nullptr;

      sCurrentThreadTLS.set(mLastCurrentThread);
      mQueue->mTailDispatcher = nullptr;
    }

   private:
    Maybe mTaskDispatcher;
    TaskQueue* mQueue;
    AbstractThread* mLastCurrentThread;
  };

  TaskDispatcher* mTailDispatcher;

  // True if we've dispatched an event to the target to execute events from
  // the queue.
  bool mIsRunning;

  // True if we've started our shutdown process.
  bool mIsShutdown;
  MozPromiseHolder mShutdownPromise;

  // The name of this TaskQueue. Useful when debugging dispatch failures.
  const char* const mName;

  SimpleTaskQueue mDirectTasks;

  class Runner : public Runnable {
   public:
    explicit Runner(TaskQueue* aQueue)
        : Runnable("TaskQueue::Runner"), mQueue(aQueue) {}
    NS_IMETHOD Run() override;

   private:
    RefPtr mQueue;
  };
};

}  // namespace mozilla

Minimal test - lines (142, 145)

path: .spaces[0].spaces[0].spaces[4].metrics.cyclomatic.average
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[4].metrics.cyclomatic.sum
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[4].metrics.cognitive.average
old: 2.0
new: null

path: .spaces[0].spaces[0].spaces[4].metrics.cognitive.sum
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.mi.mi_sei
old: 85.91942054961967
new: 111.37444718573404

path: .spaces[0].spaces[0].spaces[4].metrics.mi.mi_original
old: 87.23588298945288
new: 129.60014002899223

path: .spaces[0].spaces[0].spaces[4].metrics.mi.mi_visual_studio
old: 51.01513625114203
new: 75.78955557251007

path: .spaces[0].spaces[0].spaces[4].metrics.nargs.sum
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.nargs.average
old: 2.0
new: null

path: .spaces[0].spaces[0].spaces[4].metrics.nexits.average
old: 0.0
new: null

path: .spaces[0].spaces[0].spaces[4].metrics.nom.total
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.nom.functions
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.estimated_program_length
old: 142.09567279432156
new: 23.21928094887362

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.time
old: 303.33075549136083
new: 5.075167922744582

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.level
old: 0.09504132231404958
new: 0.4

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.difficulty
old: 10.521739130434783
new: 2.5

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.length
old: 102.0
new: 11.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.n1
old: 11.0
new: 5.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.purity_ratio
old: 1.393094831316878
new: 2.110843722624874

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.bugs
old: 0.10335656004826754
new: 0.006761255684837643

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.n2
old: 23.0
new: 5.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.N2
old: 44.0
new: 5.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.N1
old: 58.0
new: 6.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.volume
old: 518.9212098075346
new: 36.541209043760986

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.vocabulary
old: 34.0
new: 10.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.effort
old: 5459.953598844495
new: 91.35302260940249

path: .spaces[0].spaces[0].spaces[4].metrics.loc.blank
old: 3.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.lloc
old: 7.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.sloc
old: 23.0
new: 4.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.cloc
old: 6.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.ploc
old: 14.0
new: 4.0

Code

  typedef struct TaskStruct {
    nsCOMPtr event;
    uint32_t flags;
  } TaskStruct;

Minimal test - lines (65, 77)

path: .spaces[0].spaces[0].spaces[1].metrics.nargs.average
old: 1.0
new: 2.0

path: .spaces[0].spaces[0].spaces[1].metrics.nargs.sum
old: 1.0
new: 2.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.N2
old: 3.0
new: 17.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.N1
old: 4.0
new: 18.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.vocabulary
old: 7.0
new: 22.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.difficulty
old: 2.0
new: 5.884615384615385

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.time
old: 2.1834982727114696
new: 51.02618871325369

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.bugs
old: 0.0038532659414573967
new: 0.031496031486345645

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.level
old: 0.5
new: 0.1699346405228758

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.n1
old: 4.0
new: 9.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 1.8221267860233523
new: 2.189572609966143

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.length
old: 7.0
new: 35.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.effort
old: 39.302968908806456
new: 918.4713968385664

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.n2
old: 3.0
new: 13.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 12.754887502163468
new: 76.63504134881501

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.volume
old: 19.651484454403228
new: 156.0801066523054

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_original
old: 137.4860859464573
new: 102.9558996350324

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_sei
old: 161.74399477282634
new: 113.9165496360271

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 80.40121985172942
new: 60.208128441539415

path: .spaces[0].spaces[0].spaces[1].metrics.nexits.average
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.nexits.sum
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.lloc
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.cloc
old: 1.0
new: 5.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.ploc
old: 2.0
new: 9.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.sloc
old: 3.0
new: 13.0

Code

  NS_IMETHOD Dispatch(already_AddRefed aEvent,
                      uint32_t aFlags) override {
    nsCOMPtr runnable = aEvent;
    {
      MonitorAutoLock mon(mQueueMonitor);
      return DispatchLocked(/* passed by ref */ runnable, aFlags,
                            NormalDispatch);
    }
    // If the ownership of |r| is not transferred in DispatchLocked() due to
    // dispatch failure, it will be deleted here outside the lock. We do so
    // since the destructor of the runnable might access TaskQueue and result
    // in deadlocks.
  }

Minimal test - lines (79, 91)

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.length
old: 48.0
new: 38.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.difficulty
old: 7.7
new: 5.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.time
old: 96.51569554583044
new: 48.3968263965011

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.level
old: 0.12987012987012986
new: 0.2

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.purity_ratio
old: 2.0136897237320426
new: 2.3157894736842106

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.N1
old: 27.0
new: 18.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.volume
old: 225.6211064707724
new: 174.2285750274039

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.effort
old: 1737.2825198249477
new: 871.1428751370197

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.n2
old: 15.0
new: 16.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.estimated_program_length
old: 96.65710673913804
new: 88.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.N2
old: 21.0
new: 20.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.vocabulary
old: 26.0
new: 24.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.n1
old: 11.0
new: 8.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.bugs
old: 0.04817174498000614
new: 0.030404533049442024

path: .spaces[0].spaces[0].spaces[2].metrics.nexits.sum
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.nexits.average
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.sloc
old: 11.0
new: 13.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.blank
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.ploc
old: 6.0
new: 9.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.cloc
old: 4.0
new: 5.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.lloc
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.mi.mi_visual_studio
old: 60.67019871620557
new: 59.87362944924398

path: .spaces[0].spaces[0].spaces[2].metrics.mi.mi_original
old: 103.74603980471151
new: 102.3839063582072

path: .spaces[0].spaces[0].spaces[2].metrics.mi.mi_sei
old: 114.28101564363251
new: 113.09133777212956

Code

  [[nodiscard]] nsresult Dispatch(
      already_AddRefed aRunnable,
      DispatchReason aReason = NormalDispatch) override {
    nsCOMPtr r = aRunnable;
    {
      MonitorAutoLock mon(mQueueMonitor);
      return DispatchLocked(/* passed by ref */ r, NS_DISPATCH_NORMAL, aReason);
    }
    // If the ownership of |r| is not transferred in DispatchLocked() due to
    // dispatch failure, it will be deleted here outside the lock. We do so
    // since the destructor of the runnable might access TaskQueue and result
    // in deadlocks.
  }

Minimal test - lines (51, 51)

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.vocabulary
old: 7.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n2
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 12.754887502163468
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.8221267860233523
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N1
old: 4.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 19.651484454403228
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 2.1834982727114696
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 39.302968908806456
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 7.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.0038532659414573967
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: 0.5
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n1
old: 4.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: 137.4860859464573
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 80.40121985172942
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: 161.74399477282634
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.loc.sloc
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.ploc
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.cloc
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.nargs.average
old: 1.0
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.nargs.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: null

path: .spaces[0].spaces[0].spaces[0].metrics.nom.total
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.nom.functions
old: 1.0
new: 0.0

Code

  class EventTargetWrapper;

Minimal test - lines (211, 219)

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.time
old: 46.62735389278164
new: 42.38850353889241

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.bugs
old: 0.029658846884227635
new: 0.027832943532684742

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.purity_ratio
old: 1.591797727666085
new: 1.7509775004326935

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.volume
old: 134.88627376126118
new: 122.62388523751017

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.effort
old: 839.2923700700695
new: 762.9930637000633

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.N1
old: 19.0
new: 16.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.length
old: 33.0
new: 30.0

path: .spaces[0].spaces[0].spaces[6].metrics.cyclomatic.sum
old: 1.0
new: 2.0

path: .spaces[0].spaces[0].spaces[6].metrics.mi.mi_visual_studio
old: 66.51649657884488
new: 64.29095224950674

path: .spaces[0].spaces[0].spaces[6].metrics.mi.mi_original
old: 113.74320914982474
new: 109.93752834665652

path: .spaces[0].spaces[0].spaces[6].metrics.mi.mi_sei
old: 125.3293992247795
new: 83.10911468010737

path: .spaces[0].spaces[0].spaces[6].metrics.loc.cloc
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[6].metrics.loc.ploc
old: 4.0
new: 8.0

path: .spaces[0].spaces[0].spaces[6].metrics.loc.sloc
old: 7.0
new: 9.0

path: .spaces[0].spaces[0].spaces[6].metrics.loc.lloc
old: 2.0
new: 0.0

Code

  class Runner : public Runnable {
   public:
    explicit Runner(TaskQueue* aQueue)
        : Runnable("TaskQueue::Runner"), mQueue(aQueue) {}
    NS_IMETHOD Run() override;

   private:
    RefPtr mQueue;
  };

Minimal test - lines (161, 194)

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.N1
old: 17.0
new: 68.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.purity_ratio
old: 1.6972127135121615
new: 1.2112837161506158

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.length
old: 34.0
new: 125.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.n1
old: 7.0
new: 14.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.bugs
old: 0.027927562968321624
new: 0.1719920577434781

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.estimated_program_length
old: 57.70523225941349
new: 151.41046451882698

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.effort
old: 766.8871161743452
new: 11720.454974860697

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.n2
old: 11.0
new: 22.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.time
old: 42.604839787463625
new: 651.136387492261

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.vocabulary
old: 18.0
new: 36.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.difficulty
old: 5.409090909090909
new: 18.136363636363637

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.level
old: 0.18487394957983191
new: 0.05513784461152882

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.N2
old: 17.0
new: 57.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.volume
old: 141.7774500490386
new: 646.240625180289

path: .spaces[0].spaces[0].spaces[5].metrics.nargs.sum
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[5].metrics.nargs.average
old: 3.0
new: 0.5

path: .spaces[0].spaces[0].spaces[5].metrics.cyclomatic.sum
old: 1.0
new: 3.0

path: .spaces[0].spaces[0].spaces[5].metrics.mi.mi_visual_studio
old: 66.36497719023775
new: 46.510447673239774

path: .spaces[0].spaces[0].spaces[5].metrics.mi.mi_sei
old: 115.7564091601054
new: 61.55170262408128

path: .spaces[0].spaces[0].spaces[5].metrics.mi.mi_original
old: 113.48411099530654
new: 79.53286552124001

path: .spaces[0].spaces[0].spaces[5].metrics.nom.functions
old: 1.0
new: 2.0

path: .spaces[0].spaces[0].spaces[5].metrics.nom.total
old: 1.0
new: 2.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.cloc
old: 1.0
new: 3.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.blank
old: 0.0
new: 5.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.ploc
old: 6.0
new: 26.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.lloc
old: 3.0
new: 13.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.sloc
old: 7.0
new: 34.0

Code

  class AutoTaskGuard {
   public:
    explicit AutoTaskGuard(TaskQueue* aQueue)
        : mQueue(aQueue), mLastCurrentThread(nullptr) {
      // NB: We don't hold the lock to aQueue here. Don't do anything that
      // might require it.
      MOZ_ASSERT(!mQueue->mTailDispatcher);
      mTaskDispatcher.emplace(aQueue,
                              /* aIsTailDispatcher = */ true);
      mQueue->mTailDispatcher = mTaskDispatcher.ptr();

      mLastCurrentThread = sCurrentThreadTLS.get();
      sCurrentThreadTLS.set(aQueue);

      MOZ_ASSERT(mQueue->mRunningThread == nullptr);
      mQueue->mRunningThread = PR_GetCurrentThread();
    }

    ~AutoTaskGuard() {
      mTaskDispatcher->DrainDirectTasks();
      mTaskDispatcher.reset();

      MOZ_ASSERT(mQueue->mRunningThread == PR_GetCurrentThread());
      mQueue->mRunningThread = nullptr;

      sCurrentThreadTLS.set(mLastCurrentThread);
      mQueue->mTailDispatcher = nullptr;
    }

   private:
    Maybe mTaskDispatcher;
    TaskQueue* mQueue;
    AbstractThread* mLastCurrentThread;
  };