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