# 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;
      };