# Global Metrics

path: .metrics.halstead.purity_ratio
old: 1.3546953537145312
new: 0.9844312689138702
path: .metrics.halstead.effort
old: 130002.6132808472
new: 71073.91479577204
path: .metrics.halstead.n2
old: 153.0
new: 47.0
path: .metrics.halstead.volume
old: 6342.601987235211
new: 2141.3294842315936
path: .metrics.halstead.time
old: 7222.367404491511
new: 3948.550821987335
path: .metrics.halstead.difficulty
old: 20.49673202614379
new: 33.191489361702125
path: .metrics.halstead.N1
old: 411.0
new: 197.0
path: .metrics.halstead.estimated_program_length
old: 1163.6833088407825
new: 347.5042379265962
path: .metrics.halstead.vocabulary
old: 167.0
new: 67.0
path: .metrics.halstead.N2
old: 448.0
new: 156.0
path: .metrics.halstead.length
old: 859.0
new: 353.0
path: .metrics.halstead.bugs
old: 0.8554214449783866
new: 0.5719423254376421
path: .metrics.halstead.level
old: 0.04878826530612245
new: 0.030128205128205132
path: .metrics.halstead.n1
old: 14.0
new: 20.0
path: .metrics.cognitive.average
old: 0.0
new: 1.7142857142857142
path: .metrics.cognitive.sum
old: 0.0
new: 12.0
path: .metrics.mi.mi_original
old: 36.013667506833215
new: 47.52659684176558
path: .metrics.mi.mi_visual_studio
old: 21.06062427300188
new: 27.793331486412622
path: .metrics.mi.mi_sei
old: 1.4593975294348986
new: 26.934832078664627
path: .metrics.nom.functions
old: 1.0
new: 7.0
path: .metrics.nom.total
old: 1.0
new: 7.0
path: .metrics.loc.lloc
old: 2.0
new: 26.0
path: .metrics.loc.blank
old: 11.0
new: 20.0
path: .metrics.loc.ploc
old: 178.0
new: 86.0
path: .metrics.loc.cloc
old: 22.0
new: 27.0
path: .metrics.loc.sloc
old: 211.0
new: 133.0
path: .metrics.nexits.sum
old: 1.0
new: 7.0
path: .metrics.nargs.average
old: 0.0
new: 1.7142857142857142
path: .metrics.nargs.sum
old: 0.0
new: 12.0
path: .metrics.cyclomatic.sum
old: 12.0
new: 19.0
path: .metrics.cyclomatic.average
old: 1.0
new: 1.9

# Spaces Data

## Minimal test - lines (17, 131)

path: .spaces[0].metrics.nom.total
old: 0.0
new: 7.0
path: .spaces[0].metrics.nom.functions
old: 0.0
new: 7.0
path: .spaces[0].metrics.halstead.level
old: null
new: 0.028
path: .spaces[0].metrics.halstead.volume
old: 0.0
new: 2066.1061197042454
path: .spaces[0].metrics.halstead.purity_ratio
old: null
new: 0.901774909667018
path: .spaces[0].metrics.halstead.vocabulary
old: 1.0
new: 62.0
path: .spaces[0].metrics.halstead.length
old: 1.0
new: 347.0
path: .spaces[0].metrics.halstead.difficulty
old: 0.0
new: 35.714285714285715
path: .spaces[0].metrics.halstead.effort
old: 0.0
new: 73789.50427515163
path: .spaces[0].metrics.halstead.n1
old: 0.0
new: 20.0
path: .spaces[0].metrics.halstead.n2
old: 1.0
new: 42.0
path: .spaces[0].metrics.halstead.N2
old: 1.0
new: 150.0
path: .spaces[0].metrics.halstead.time
old: 0.0
new: 4099.41690417509
path: .spaces[0].metrics.halstead.N1
old: 0.0
new: 197.0
path: .spaces[0].metrics.halstead.bugs
old: 0.0
new: 0.5864195951257065
path: .spaces[0].metrics.halstead.estimated_program_length
old: null
new: 312.9158936544552
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 18.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 2.0
path: .spaces[0].metrics.loc.sloc
old: 1.0
new: 115.0
path: .spaces[0].metrics.loc.lloc
old: 0.0
new: 26.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 17.0
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 20.0
path: .spaces[0].metrics.loc.ploc
old: 1.0
new: 78.0
path: .spaces[0].metrics.nargs.average
old: null
new: 1.7142857142857142
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 12.0
path: .spaces[0].metrics.mi.mi_original
old: null
new: 50.2983102520119
path: .spaces[0].metrics.mi.mi_sei
old: null
new: 28.799216991517465
path: .spaces[0].metrics.mi.mi_visual_studio
old: null
new: 29.41421652164439
path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 7.0
path: .spaces[0].metrics.nexits.average
old: null
new: 1.0
path: .spaces[0].metrics.cognitive.average
old: null
new: 1.7142857142857142
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 12.0

### Code

    namespace mozilla {

    /**
     * This class will wrap a nsIRunnable and dispatch it to the main thread
     * synchronously. This is different from nsIEventTarget.DISPATCH_SYNC:
     * this class does not spin the event loop waiting for the event to be
     * dispatched. This means that you don't risk reentrance from pending
     * messages, but you must be sure that the target thread does not ever block
     * on this thread, or else you will deadlock.
     *
     * Typical usage:
     * RefPtr sr = new SyncRunnable(new myrunnable...());
     * sr->DispatchToThread(t);
     *
     * We also provide a convenience wrapper:
     * SyncRunnable::DispatchToThread(new myrunnable...());
     *
     */
    class SyncRunnable : public Runnable {
     public:
      explicit SyncRunnable(nsIRunnable* aRunnable)
          : Runnable("SyncRunnable"),
            mRunnable(aRunnable),
            mMonitor("SyncRunnable"),
            mDone(false) {}

      explicit SyncRunnable(already_AddRefed aRunnable)
          : Runnable("SyncRunnable"),
            mRunnable(std::move(aRunnable)),
            mMonitor("SyncRunnable"),
            mDone(false) {}

      nsresult DispatchToThread(nsIEventTarget* aThread,
                                bool aForceDispatch = false) {
        nsresult rv;
        bool on;

        if (!aForceDispatch) {
          rv = aThread->IsOnCurrentThread(&on);
          MOZ_ASSERT(NS_SUCCEEDED(rv));
          if (NS_SUCCEEDED(rv) && on) {
            mRunnable->Run();
            return NS_OK;
          }
        }

        rv = aThread->Dispatch(this, NS_DISPATCH_NORMAL);
        if (NS_SUCCEEDED(rv)) {
          mozilla::MonitorAutoLock lock(mMonitor);
          // This could be synchronously dispatching to a thread currently waiting
          // for JS execution clearance. Yield JS execution.
          dom::AutoYieldJSThreadExecution yield;

          while (!mDone) {
            lock.Wait();
          }
        }
        return rv;
      }

      nsresult DispatchToThread(AbstractThread* aThread,
                                bool aForceDispatch = false) {
        if (!aForceDispatch && aThread->IsCurrentThreadIn()) {
          mRunnable->Run();
          return NS_OK;
        }

        // Check we don't have tail dispatching here. Otherwise we will deadlock
        // ourself when spinning the loop below.
        MOZ_ASSERT(!aThread->RequiresTailDispatchFromCurrentThread());

        nsresult rv = aThread->Dispatch(RefPtr(this).forget());
        if (NS_SUCCEEDED(rv)) {
          mozilla::MonitorAutoLock lock(mMonitor);
          while (!mDone) {
            lock.Wait();
          }
        }
        return rv;
      }

      static nsresult DispatchToThread(nsIEventTarget* aThread,
                                       nsIRunnable* aRunnable,
                                       bool aForceDispatch = false) {
        RefPtr s(new SyncRunnable(aRunnable));
        return s->DispatchToThread(aThread, aForceDispatch);
      }

      static nsresult DispatchToThread(AbstractThread* aThread,
                                       nsIRunnable* aRunnable,
                                       bool aForceDispatch = false) {
        RefPtr s(new SyncRunnable(aRunnable));
        return s->DispatchToThread(aThread, aForceDispatch);
      }

     protected:
      NS_IMETHOD Run() override {
        mRunnable->Run();

        mozilla::MonitorAutoLock lock(mMonitor);
        MOZ_ASSERT(!mDone);

        mDone = true;
        mMonitor.Notify();

        return NS_OK;
      }

     private:
      nsCOMPtr mRunnable;
      mozilla::Monitor mMonitor;
      bool mDone;
    };

    }  // namespace mozilla