Global Metrics

path: .metrics.cognitive.average
old: 0.0
new: 0.08695652173913043

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

path: .metrics.cyclomatic.average
old: 1.0
new: 1.236842105263158

path: .metrics.cyclomatic.sum
old: 9.0
new: 47.0

path: .metrics.halstead.level
old: 0.061952861952861954
new: 0.027791705465224553

path: .metrics.halstead.effort
old: 27586.082713186406
new: 407184.14028473577

path: .metrics.halstead.N2
old: 135.0
new: 607.0

path: .metrics.halstead.volume
old: 1709.0367741502691
new: 11316.341696904052

path: .metrics.halstead.vocabulary
old: 57.0
new: 217.0

path: .metrics.halstead.difficulty
old: 16.141304347826086
new: 35.9819587628866

path: .metrics.halstead.length
old: 293.0
new: 1458.0

path: .metrics.halstead.N1
old: 158.0
new: 851.0

path: .metrics.halstead.bugs
old: 0.30432579693911416
new: 1.8312149051497464

path: .metrics.halstead.estimated_program_length
old: 292.1375977836329
new: 1578.4250163736142

path: .metrics.halstead.time
old: 1532.5601507325782
new: 22621.341126929765

path: .metrics.halstead.purity_ratio
old: 0.9970566477257096
new: 1.082596033178062

path: .metrics.halstead.n1
old: 11.0
new: 23.0

path: .metrics.halstead.n2
old: 46.0
new: 194.0

path: .metrics.nargs.average
old: 2.2857142857142856
new: 0.8695652173913043

path: .metrics.nargs.sum
old: 16.0
new: 20.0

path: .metrics.mi.mi_sei
old: 41.937675826903856
new: -39.65212118668394

path: .metrics.mi.mi_visual_studio
old: 36.04111788378195
new: 0.20954296135882763

path: .metrics.mi.mi_original
old: 61.63031158126714
new: 0.35831846392359523

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

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

path: .metrics.loc.blank
old: 8.0
new: 446.0

path: .metrics.loc.ploc
old: 51.0
new: 341.0

path: .metrics.loc.cloc
old: 10.0
new: 176.0

path: .metrics.loc.sloc
old: 69.0
new: 963.0

path: .metrics.loc.lloc
old: 23.0
new: 48.0

path: .metrics.nexits.average
old: 0.7142857142857143
new: 0.6521739130434783

path: .metrics.nexits.sum
old: 5.0
new: 15.0

Spaces Data

Minimal test - lines (96, 120)

path: .spaces[0].spaces[5].metrics.halstead.purity_ratio
old: 1.7818257188470974
new: 0.6060101260867115

path: .spaces[0].spaces[5].metrics.halstead.bugs
old: 0.04245684983318792
new: 0.19967269424074788

path: .spaces[0].spaces[5].metrics.halstead.length
old: 40.0
new: 188.0

path: .spaces[0].spaces[5].metrics.halstead.vocabulary
old: 21.0
new: 29.0

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

path: .spaces[0].spaces[5].metrics.halstead.level
old: 0.12222222222222222
new: 0.06229508196721311

path: .spaces[0].spaces[5].metrics.halstead.N2
old: 18.0
new: 61.0

path: .spaces[0].spaces[5].metrics.halstead.difficulty
old: 8.181818181818182
new: 16.05263157894737

path: .spaces[0].spaces[5].metrics.halstead.N1
old: 22.0
new: 127.0

path: .spaces[0].spaces[5].metrics.halstead.volume
old: 175.69269691115042
new: 913.3004270839835

path: .spaces[0].spaces[5].metrics.halstead.effort
old: 1437.4857020003217
new: 14660.875276874474

path: .spaces[0].spaces[5].metrics.halstead.estimated_program_length
old: 71.27302875388389
new: 113.92990370430176

path: .spaces[0].spaces[5].metrics.halstead.time
old: 79.86031677779565
new: 814.4930709374707

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

path: .spaces[0].spaces[5].metrics.mi.mi_sei
old: 118.36545937409804
new: 44.16781209758042

path: .spaces[0].spaces[5].metrics.mi.mi_original
old: 110.20561759577762
new: 82.94547425424624

path: .spaces[0].spaces[5].metrics.mi.mi_visual_studio
old: 64.44772958817404
new: 48.50612529488084

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

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

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

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

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

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

path: .spaces[0].spaces[5].metrics.loc.sloc
old: 8.0
new: 25.0

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

path: .spaces[0].spaces[5].metrics.loc.ploc
old: 7.0
new: 22.0

Code

struct TraceCallbackFunc : public TraceCallbacks {
  typedef void (*Func)(JS::GCCellPtr aPtr, const char* aName, void* aClosure);

  explicit TraceCallbackFunc(Func aCb) : mCallback(aCb) {}

  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(nsWrapperCache* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;

 private:
  Func mCallback;
};

Minimal test - lines (58, 58)

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

path: .spaces[0].spaces[2].metrics.loc.lloc
old: 4.0
new: 0.0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Code

class nsWrapperCache;

Minimal test - lines (56, 56)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Code

class nsCycleCollectionTraversalCallback;

Minimal test - lines (60, 65)

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

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

path: .spaces[0].spaces[3].metrics.loc.lloc
old: 3.0
new: 0.0

path: .spaces[0].spaces[3].metrics.mi.mi_sei
old: 85.5876177277901
new: 100.53618767522336

path: .spaces[0].spaces[3].metrics.mi.mi_original
old: 111.72607189463828
new: 121.94647871016232

path: .spaces[0].spaces[3].metrics.mi.mi_visual_studio
old: 65.33688414891127
new: 71.313730239861

path: .spaces[0].spaces[3].metrics.halstead.length
old: 46.0
new: 13.0

path: .spaces[0].spaces[3].metrics.halstead.purity_ratio
old: 1.4443165629945054
new: 1.5084338826489854

path: .spaces[0].spaces[3].metrics.halstead.level
old: 0.09523809523809525
new: 0.4166666666666667

path: .spaces[0].spaces[3].metrics.halstead.bugs
old: 0.054445483288631406
new: 0.0071287677522191

path: .spaces[0].spaces[3].metrics.halstead.n2
old: 10.0
new: 5.0

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

path: .spaces[0].spaces[3].metrics.halstead.N2
old: 21.0
new: 6.0

path: .spaces[0].spaces[3].metrics.halstead.effort
old: 2087.491269830596
new: 98.90166004500011

path: .spaces[0].spaces[3].metrics.halstead.volume
old: 198.80869236481868
new: 41.209025018750054

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

path: .spaces[0].spaces[3].metrics.halstead.estimated_program_length
old: 66.43856189774725
new: 19.60964047443681

path: .spaces[0].spaces[3].metrics.halstead.vocabulary
old: 20.0
new: 9.0

path: .spaces[0].spaces[3].metrics.halstead.time
old: 115.9717372128109
new: 5.494536669166674

path: .spaces[0].spaces[3].metrics.halstead.difficulty
old: 10.5
new: 2.4

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

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

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

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

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

Code

namespace JS {
template 
class Heap;
template 
class TenuredHeap;
} /* namespace JS */

Minimal test - lines (57, 57)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Code

class nsISupports;

Minimal test - lines (48, 254)

path: .spaces[0].metrics.halstead.difficulty
old: 16.88372093023256
new: 35.397260273972606

path: .spaces[0].metrics.halstead.effort
old: 28177.535225709227
new: 170647.08692876066

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

path: .spaces[0].metrics.halstead.time
old: 1565.4186236505127
new: 9480.39371826448

path: .spaces[0].metrics.halstead.vocabulary
old: 54.0
new: 92.0

path: .spaces[0].metrics.halstead.level
old: 0.05922865013774104
new: 0.02825077399380805

path: .spaces[0].metrics.halstead.volume
old: 1668.9173756274058
new: 4820.912285526133

path: .spaces[0].metrics.halstead.estimated_program_length
old: 271.3831322572005
new: 532.5678155536693

path: .spaces[0].metrics.halstead.N1
old: 158.0
new: 467.0

path: .spaces[0].metrics.halstead.length
old: 290.0
new: 739.0

path: .spaces[0].metrics.halstead.N2
old: 132.0
new: 272.0

path: .spaces[0].metrics.halstead.bugs
old: 0.3086602802717067
new: 1.0255212516392678

path: .spaces[0].metrics.halstead.purity_ratio
old: 0.935803904335174
new: 0.7206601022377123

path: .spaces[0].metrics.halstead.n2
old: 43.0
new: 73.0

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

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

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

path: .spaces[0].metrics.loc.ploc
old: 47.0
new: 115.0

path: .spaces[0].metrics.loc.sloc
old: 57.0
new: 207.0

path: .spaces[0].metrics.loc.blank
old: 6.0
new: 22.0

path: .spaces[0].metrics.loc.lloc
old: 23.0
new: 26.0

path: .spaces[0].metrics.mi.mi_original
old: 65.07893129205475
new: 34.300219557146676

path: .spaces[0].metrics.mi.mi_sei
old: 38.95116853862184
new: 15.726884480538295

path: .spaces[0].metrics.mi.mi_visual_studio
old: 38.05785455675717
new: 20.05860792815595

path: .spaces[0].metrics.nexits.sum
old: 5.0
new: 10.0

path: .spaces[0].metrics.cyclomatic.sum
old: 8.0
new: 27.0

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

path: .spaces[0].metrics.nargs.sum
old: 16.0
new: 13.0

path: .spaces[0].metrics.nargs.average
old: 2.2857142857142856
new: 0.9285714285714286

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

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

Code

class nsCycleCollectionISupports {
 public:
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID)
};

NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports,
                              NS_CYCLECOLLECTIONISUPPORTS_IID)

class nsCycleCollectionTraversalCallback;
class nsISupports;
class nsWrapperCache;

namespace JS {
template 
class Heap;
template 
class TenuredHeap;
} /* namespace JS */

/*
 * A struct defining pure virtual methods which are called when tracing cycle
 * collection paticipants.  The appropriate method is called depending on the
 * type of JS GC thing.
 */
struct TraceCallbacks {
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(nsWrapperCache* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
};

/*
 * An implementation of TraceCallbacks that calls a single function for all JS
 * GC thing types encountered. Implemented in
 * nsCycleCollectorTraceJSHelpers.cpp.
 */
struct TraceCallbackFunc : public TraceCallbacks {
  typedef void (*Func)(JS::GCCellPtr aPtr, const char* aName, void* aClosure);

  explicit TraceCallbackFunc(Func aCb) : mCallback(aCb) {}

  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(nsWrapperCache* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const override;

 private:
  Func mCallback;
};

/**
 * Participant implementation classes
 */
class NS_NO_VTABLE nsCycleCollectionParticipant {
 public:
  using Flags = uint8_t;
  static constexpr Flags FlagMightSkip = 1u << 0;
  static constexpr Flags FlagTraverseShouldTrace = 1u << 1;
  static constexpr Flags FlagMultiZoneJSHolder = 1u << 2;
  static constexpr Flags AllFlags =
      FlagMightSkip | FlagTraverseShouldTrace | FlagMultiZoneJSHolder;

  constexpr explicit nsCycleCollectionParticipant(Flags aFlags)
      : mFlags(aFlags) {
    MOZ_ASSERT((aFlags & ~AllFlags) == 0);
  }

  NS_IMETHOD TraverseNative(void* aPtr,
                            nsCycleCollectionTraversalCallback& aCb) = 0;

  nsresult TraverseNativeAndJS(void* aPtr,
                               nsCycleCollectionTraversalCallback& aCb) {
    nsresult rv = TraverseNative(aPtr, aCb);
    if (TraverseShouldTrace()) {
      // Note, we always call Trace, even if Traverse returned
      // NS_SUCCESS_INTERRUPTED_TRAVERSE.
      TraceCallbackFunc noteJsChild(&nsCycleCollectionParticipant::NoteJSChild);
      Trace(aPtr, noteJsChild, &aCb);
    }
    return rv;
  }

  // Implemented in nsCycleCollectorTraceJSHelpers.cpp.
  static void NoteJSChild(JS::GCCellPtr aGCThing, const char* aName,
                          void* aClosure);

  NS_IMETHOD_(void) Root(void* aPtr) = 0;
  NS_IMETHOD_(void) Unlink(void* aPtr) = 0;
  NS_IMETHOD_(void) Unroot(void* aPtr) = 0;
  NS_IMETHOD_(const char*) ClassName() = 0;

  NS_IMETHOD_(void)
  Trace(void* aPtr, const TraceCallbacks& aCb, void* aClosure) {}

  // CanSkip is called during nsCycleCollector_forgetSkippable.  If it returns
  // true, aPtr is removed from the purple buffer and therefore might be left
  // out from the cycle collector graph the next time that's constructed (unless
  // it's reachable in some other way).
  //
  // CanSkip is allowed to expand the set of certainly-alive objects by removing
  // other objects from the purple buffer, marking JS things black (in the GC
  // sense), and so forth.  Furthermore, if aRemovingAllowed is true, this call
  // is allowed to remove aPtr itself from the purple buffer.
  //
  // Things can return true from CanSkip if either they know they have no
  // outgoing edges at all in the cycle collection graph (because then they
  // can't be parts of a cycle) or they know for sure they're alive.
  bool CanSkip(void* aPtr, bool aRemovingAllowed) {
    return MightSkip() ? CanSkipReal(aPtr, aRemovingAllowed) : false;
  }

  // CanSkipInCC is called during construction of the initial set of roots for
  // the cycle collector graph.  If it returns true, aPtr is left out of that
  // set of roots.  Note that the set of roots includes whatever is in the
  // purple buffer (after earlier CanSkip calls) plus various other sources of
  // roots, so an object can end up having CanSkipInCC called on it even if it
  // returned true from CanSkip.  One example of this would be an object that
  // can potentially trace JS things.
  //
  // CanSkipInCC is allowed to remove other objects from the purple buffer but
  // should not remove aPtr and should not mark JS things black.  It should also
  // not modify any reference counts.
  //
  // Things can return true from CanSkipInCC if either they know they have no
  // outgoing edges at all in the cycle collection graph or they know for sure
  // they're alive _and_ none of their outgoing edges are to gray (in the GC
  // sense) gcthings.  See also nsWrapperCache::HasNothingToTrace and
  // nsWrapperCache::HasKnownLiveWrapperAndDoesNotNeedTracing. The restriction
  // on not having outgoing edges to gray gcthings is because if we _do_ have
  // them that means we have a "strong" edge to a JS thing and since we're alive
  // we need to trace through it and mark keep them alive.  Outgoing edges to
  // C++ things don't matter here, because the criteria for when a CC
  // participant is considered alive are slightly different for JS and C++
  // things: JS things are only considered alive when reachable via an edge from
  // a live thing, while C++ things are also considered alive when their
  // refcount exceeds the number of edges via which they are reachable.
  bool CanSkipInCC(void* aPtr) {
    return MightSkip() ? CanSkipInCCReal(aPtr) : false;
  }

  // CanSkipThis is called during construction of the cycle collector graph,
  // when we traverse an edge to aPtr and consider adding it to the graph.  If
  // it returns true, aPtr is not added to the graph.
  //
  // CanSkipThis is not allowed to change the liveness or reference count of any
  // objects.
  //
  // Things can return true from CanSkipThis if either they know they have no
  // outgoing edges at all in the cycle collection graph or they know for sure
  // they're alive.
  //
  // Note that CanSkipThis doesn't have to worry about outgoing edges to gray GC
  // things, because if this object could have those it already got added to the
  // graph during root set construction.  An object should never have
  // CanSkipThis called on it if it has outgoing strong references to JS things.
  bool CanSkipThis(void* aPtr) {
    return MightSkip() ? CanSkipThisReal(aPtr) : false;
  }

  NS_IMETHOD_(void) DeleteCycleCollectable(void* aPtr) = 0;

  bool IsMultiZoneJSHolder() const { return mFlags & FlagMultiZoneJSHolder; }

 protected:
  NS_IMETHOD_(bool) CanSkipReal(void* aPtr, bool aRemovingAllowed) {
    NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
    return false;
  }
  NS_IMETHOD_(bool) CanSkipInCCReal(void* aPtr) {
    NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
    return false;
  }
  NS_IMETHOD_(bool) CanSkipThisReal(void* aPtr) {
    NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
    return false;
  }

 private:
  bool MightSkip() const { return mFlags & FlagMightSkip; }
  bool TraverseShouldTrace() const { return mFlags & FlagTraverseShouldTrace; }

  const Flags mFlags;
};

Minimal test - lines (125, 239)

path: .spaces[0].spaces[6].metrics.mi.mi_visual_studio
old: 61.44637168252373
new: 30.596718596661898

path: .spaces[0].spaces[6].metrics.mi.mi_original
old: 105.0732955771156
new: 52.32038880029184

path: .spaces[0].spaces[6].metrics.mi.mi_sei
old: 99.51648244530158
new: 45.228071221615984

path: .spaces[0].spaces[6].metrics.loc.ploc
old: 10.0
new: 47.0

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

path: .spaces[0].spaces[6].metrics.loc.lloc
old: 4.0
new: 20.0

path: .spaces[0].spaces[6].metrics.loc.sloc
old: 10.0
new: 115.0

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

path: .spaces[0].spaces[6].metrics.nexits.sum
old: 1.0
new: 6.0

path: .spaces[0].spaces[6].metrics.nexits.average
old: 1.0
new: 0.75

path: .spaces[0].spaces[6].metrics.halstead.difficulty
old: 9.23076923076923
new: 19.333333333333332

path: .spaces[0].spaces[6].metrics.halstead.n1
old: 10.0
new: 17.0

path: .spaces[0].spaces[6].metrics.halstead.bugs
old: 0.055893323238229015
new: 0.34830687849628833

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

path: .spaces[0].spaces[6].metrics.halstead.n2
old: 13.0
new: 51.0

path: .spaces[0].spaces[6].metrics.halstead.volume
old: 235.22522171496468
new: 1747.1018354388473

path: .spaces[0].spaces[6].metrics.halstead.effort
old: 2171.309738907366
new: 33777.30215181771

path: .spaces[0].spaces[6].metrics.halstead.purity_ratio
old: 1.5639422554751503
new: 1.2501064834209128

path: .spaces[0].spaces[6].metrics.halstead.length
old: 52.0
new: 287.0

path: .spaces[0].spaces[6].metrics.halstead.level
old: 0.10833333333333334
new: 0.05172413793103449

path: .spaces[0].spaces[6].metrics.halstead.time
old: 120.628318828187
new: 1876.5167862120952

path: .spaces[0].spaces[6].metrics.halstead.N1
old: 28.0
new: 171.0

path: .spaces[0].spaces[6].metrics.halstead.N2
old: 24.0
new: 116.0

path: .spaces[0].spaces[6].metrics.halstead.estimated_program_length
old: 81.32499728470782
new: 358.780560741802

path: .spaces[0].spaces[6].metrics.nargs.average
old: 4.0
new: 1.25

path: .spaces[0].spaces[6].metrics.nargs.sum
old: 4.0
new: 10.0

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

path: .spaces[0].spaces[6].metrics.cyclomatic.average
old: 1.0
new: 1.4444444444444444

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

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

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

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

Code

class NS_NO_VTABLE nsCycleCollectionParticipant {
 public:
  using Flags = uint8_t;
  static constexpr Flags FlagMightSkip = 1u << 0;
  static constexpr Flags FlagTraverseShouldTrace = 1u << 1;
  static constexpr Flags FlagMultiZoneJSHolder = 1u << 2;
  static constexpr Flags AllFlags =
      FlagMightSkip | FlagTraverseShouldTrace | FlagMultiZoneJSHolder;

  constexpr explicit nsCycleCollectionParticipant(Flags aFlags)
      : mFlags(aFlags) {
    MOZ_ASSERT((aFlags & ~AllFlags) == 0);
  }

  NS_IMETHOD TraverseNative(void* aPtr,
                            nsCycleCollectionTraversalCallback& aCb) = 0;

  nsresult TraverseNativeAndJS(void* aPtr,
                               nsCycleCollectionTraversalCallback& aCb) {
    nsresult rv = TraverseNative(aPtr, aCb);
    if (TraverseShouldTrace()) {
      // Note, we always call Trace, even if Traverse returned
      // NS_SUCCESS_INTERRUPTED_TRAVERSE.
      TraceCallbackFunc noteJsChild(&nsCycleCollectionParticipant::NoteJSChild);
      Trace(aPtr, noteJsChild, &aCb);
    }
    return rv;
  }

  // Implemented in nsCycleCollectorTraceJSHelpers.cpp.
  static void NoteJSChild(JS::GCCellPtr aGCThing, const char* aName,
                          void* aClosure);

  NS_IMETHOD_(void) Root(void* aPtr) = 0;
  NS_IMETHOD_(void) Unlink(void* aPtr) = 0;
  NS_IMETHOD_(void) Unroot(void* aPtr) = 0;
  NS_IMETHOD_(const char*) ClassName() = 0;

  NS_IMETHOD_(void)
  Trace(void* aPtr, const TraceCallbacks& aCb, void* aClosure) {}

  // CanSkip is called during nsCycleCollector_forgetSkippable.  If it returns
  // true, aPtr is removed from the purple buffer and therefore might be left
  // out from the cycle collector graph the next time that's constructed (unless
  // it's reachable in some other way).
  //
  // CanSkip is allowed to expand the set of certainly-alive objects by removing
  // other objects from the purple buffer, marking JS things black (in the GC
  // sense), and so forth.  Furthermore, if aRemovingAllowed is true, this call
  // is allowed to remove aPtr itself from the purple buffer.
  //
  // Things can return true from CanSkip if either they know they have no
  // outgoing edges at all in the cycle collection graph (because then they
  // can't be parts of a cycle) or they know for sure they're alive.
  bool CanSkip(void* aPtr, bool aRemovingAllowed) {
    return MightSkip() ? CanSkipReal(aPtr, aRemovingAllowed) : false;
  }

  // CanSkipInCC is called during construction of the initial set of roots for
  // the cycle collector graph.  If it returns true, aPtr is left out of that
  // set of roots.  Note that the set of roots includes whatever is in the
  // purple buffer (after earlier CanSkip calls) plus various other sources of
  // roots, so an object can end up having CanSkipInCC called on it even if it
  // returned true from CanSkip.  One example of this would be an object that
  // can potentially trace JS things.
  //
  // CanSkipInCC is allowed to remove other objects from the purple buffer but
  // should not remove aPtr and should not mark JS things black.  It should also
  // not modify any reference counts.
  //
  // Things can return true from CanSkipInCC if either they know they have no
  // outgoing edges at all in the cycle collection graph or they know for sure
  // they're alive _and_ none of their outgoing edges are to gray (in the GC
  // sense) gcthings.  See also nsWrapperCache::HasNothingToTrace and
  // nsWrapperCache::HasKnownLiveWrapperAndDoesNotNeedTracing. The restriction
  // on not having outgoing edges to gray gcthings is because if we _do_ have
  // them that means we have a "strong" edge to a JS thing and since we're alive
  // we need to trace through it and mark keep them alive.  Outgoing edges to
  // C++ things don't matter here, because the criteria for when a CC
  // participant is considered alive are slightly different for JS and C++
  // things: JS things are only considered alive when reachable via an edge from
  // a live thing, while C++ things are also considered alive when their
  // refcount exceeds the number of edges via which they are reachable.
  bool CanSkipInCC(void* aPtr) {
    return MightSkip() ? CanSkipInCCReal(aPtr) : false;
  }

  // CanSkipThis is called during construction of the cycle collector graph,
  // when we traverse an edge to aPtr and consider adding it to the graph.  If
  // it returns true, aPtr is not added to the graph.
  //
  // CanSkipThis is not allowed to change the liveness or reference count of any
  // objects.
  //
  // Things can return true from CanSkipThis if either they know they have no
  // outgoing edges at all in the cycle collection graph or they know for sure
  // they're alive.
  //
  // Note that CanSkipThis doesn't have to worry about outgoing edges to gray GC
  // things, because if this object could have those it already got added to the
  // graph during root set construction.  An object should never have
  // CanSkipThis called on it if it has outgoing strong references to JS things.
  bool CanSkipThis(void* aPtr) {
    return MightSkip() ? CanSkipThisReal(aPtr) : false;
  }

  NS_IMETHOD_(void) DeleteCycleCollectable(void* aPtr) = 0;

  bool IsMultiZoneJSHolder() const { return mFlags & FlagMultiZoneJSHolder; }

 protected:
  NS_IMETHOD_(bool) CanSkipReal(void* aPtr, bool aRemovingAllowed) {
    NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
    return false;
  }

Minimal test - lines (72, 89)

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

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

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

path: .spaces[0].spaces[4].metrics.mi.mi_original
old: 114.99771977101476
new: 89.19417174101484

path: .spaces[0].spaces[4].metrics.mi.mi_sei
old: 119.86396375533808
new: 53.08095711435233

path: .spaces[0].spaces[4].metrics.mi.mi_visual_studio
old: 67.25012852106127
new: 52.16033435147067

path: .spaces[0].spaces[4].metrics.halstead.N2
old: 18.0
new: 56.0

path: .spaces[0].spaces[4].metrics.halstead.length
old: 39.0
new: 172.0

path: .spaces[0].spaces[4].metrics.halstead.n2
old: 11.0
new: 15.0

path: .spaces[0].spaces[4].metrics.halstead.level
old: 0.12222222222222222
new: 0.05357142857142857

path: .spaces[0].spaces[4].metrics.halstead.effort
old: 1401.5485594503136
new: 14909.874273303383

path: .spaces[0].spaces[4].metrics.halstead.estimated_program_length
old: 71.27302875388389
new: 91.8226398830014

path: .spaces[0].spaces[4].metrics.halstead.bugs
old: 0.04174625403117913
new: 0.20192715796442023

path: .spaces[0].spaces[4].metrics.halstead.time
old: 77.86380885835075
new: 828.3263485168546

path: .spaces[0].spaces[4].metrics.halstead.volume
old: 171.30037948837168
new: 798.7432646412526

path: .spaces[0].spaces[4].metrics.halstead.purity_ratio
old: 1.8275135577918944
new: 0.5338525574593106

path: .spaces[0].spaces[4].metrics.halstead.N1
old: 21.0
new: 116.0

path: .spaces[0].spaces[4].metrics.halstead.difficulty
old: 8.181818181818182
new: 18.666666666666668

path: .spaces[0].spaces[4].metrics.halstead.vocabulary
old: 21.0
new: 25.0

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

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

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

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

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

path: .spaces[0].spaces[4].metrics.loc.sloc
old: 6.0
new: 18.0

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

path: .spaces[0].spaces[4].metrics.loc.ploc
old: 6.0
new: 18.0

Code

struct TraceCallbacks {
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(nsWrapperCache* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::TenuredHeap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
  virtual void Trace(JS::Heap* aPtr, const char* aName,
                     void* aClosure) const = 0;
};