LCOV - code coverage report
Current view: top level - xpcom/base - nsCOMPtr.h (source / functions) Hit Total Coverage
Test: output.info Lines: 424 453 93.6 %
Date: 2017-07-14 16:53:18 Functions: 7540 19146 39.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef nsCOMPtr_h___
       8             : #define nsCOMPtr_h___
       9             : 
      10             : /*
      11             :  * Having problems?
      12             :  *
      13             :  * See the User Manual at:
      14             :  *   http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
      15             :  *
      16             :  *
      17             :  * nsCOMPtr
      18             :  *   better than a raw pointer
      19             :  * for owning objects
      20             :  *                      -- scc
      21             :  */
      22             : 
      23             : #include "mozilla/AlreadyAddRefed.h"
      24             : #include "mozilla/Assertions.h"
      25             : #include "mozilla/Attributes.h"
      26             : #include "mozilla/Move.h"
      27             : #include "mozilla/TypeTraits.h"
      28             : 
      29             : #include "nsDebug.h" // for |NS_ASSERTION|
      30             : #include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
      31             : #include "mozilla/RefPtr.h"
      32             : 
      33             : #include "nsCycleCollectionNoteChild.h"
      34             : 
      35             : 
      36             : /*
      37             :  * WARNING: This file defines several macros for internal use only. These
      38             :  * macros begin with the prefix |NSCAP_|. Do not use these macros in your own
      39             :  * code. They are for internal use only for cross-platform compatibility, and
      40             :  * are subject to change without notice.
      41             :  */
      42             : 
      43             : 
      44             : #ifdef _MSC_VER
      45             :   // Under VC++, we win by inlining StartAssignment.
      46             :   #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
      47             : 
      48             :   // Also under VC++, at the highest warning level, we are overwhelmed with
      49             :   // warnings about (unused) inline functions being removed. This is to be
      50             :   // expected with templates, so we disable the warning.
      51             :   #pragma warning( disable: 4514 )
      52             : #endif
      53             : 
      54             : #define NSCAP_FEATURE_USE_BASE
      55             : 
      56             : #ifdef DEBUG
      57             :   #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
      58             :   #undef NSCAP_FEATURE_USE_BASE
      59             : #endif
      60             : 
      61             : #ifdef __GNUC__
      62             :   // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
      63             :   // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
      64             :   // don't reorder instructions based on aliasing assumptions for
      65             :   // this variable.  Fortunately, gcc versions < 3.3 do not do any
      66             :   // optimizations that break nsCOMPtr.
      67             : 
      68             :   #define NS_MAY_ALIAS_PTR(t)    t*  __attribute__((__may_alias__))
      69             : #else
      70             :   #define NS_MAY_ALIAS_PTR(t)    t*
      71             : #endif
      72             : 
      73             : #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
      74             :   #define NSCAP_FEATURE_USE_BASE
      75             : #endif
      76             : 
      77             : /*
      78             :  * The following three macros (NSCAP_ADDREF, NSCAP_RELEASE, and
      79             :  * NSCAP_LOG_ASSIGNMENT) allow external clients the ability to add logging or
      80             :  * other interesting debug facilities. In fact, if you want |nsCOMPtr| to
      81             :  * participate in the standard logging facility, you provide
      82             :  * (e.g., in "nsISupportsImpl.h") suitable definitions
      83             :  *
      84             :  *   #define NSCAP_ADDREF(this, ptr)         NS_ADDREF(ptr)
      85             :  *   #define NSCAP_RELEASE(this, ptr)        NS_RELEASE(ptr)
      86             :  */
      87             : 
      88             : #ifndef NSCAP_ADDREF
      89             :   #define NSCAP_ADDREF(this, ptr)     (ptr)->AddRef()
      90             : #endif
      91             : 
      92             : #ifndef NSCAP_RELEASE
      93             :   #define NSCAP_RELEASE(this, ptr)    (ptr)->Release()
      94             : #endif
      95             : 
      96             : // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
      97             : #ifdef NSCAP_LOG_ASSIGNMENT
      98             :   // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we
      99             :   // know to instantiate |~nsGetterAddRefs| in turn to note the external
     100             :   // assignment into the |nsCOMPtr|.
     101             :   #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
     102             : #else
     103             :     // ...otherwise, just strip it out of the code
     104             :   #define NSCAP_LOG_ASSIGNMENT(this, ptr)
     105             : #endif
     106             : 
     107             : #ifndef NSCAP_LOG_RELEASE
     108             :   #define NSCAP_LOG_RELEASE(this, ptr)
     109             : #endif
     110             : 
     111             : namespace mozilla {
     112             : template<class T> class OwningNonNull;
     113             : } // namespace mozilla
     114             : 
     115             : template<class T>
     116             : inline already_AddRefed<T>
     117      100990 : dont_AddRef(T* aRawPtr)
     118             : {
     119      100990 :   return already_AddRefed<T>(aRawPtr);
     120             : }
     121             : 
     122             : template<class T>
     123             : inline already_AddRefed<T>&&
     124             : dont_AddRef(already_AddRefed<T>&& aAlreadyAddRefedPtr)
     125             : {
     126             :   return mozilla::Move(aAlreadyAddRefedPtr);
     127             : }
     128             : 
     129             : 
     130             : /*
     131             :  * An nsCOMPtr_helper transforms commonly called getters into typesafe forms
     132             :  * that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
     133             :  * Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
     134             :  *
     135             :  * Here are the rules for a helper:
     136             :  *   - it implements |operator()| to produce an interface pointer
     137             :  *   - (except for its name) |operator()| is a valid [XP]COM `getter'
     138             :  *   - the interface pointer that it returns is already |AddRef()|ed (as from
     139             :  *     any good getter)
     140             :  *   - it matches the type requested with the supplied |nsIID| argument
     141             :  *   - its constructor provides an optional |nsresult*| that |operator()| can
     142             :  *     fill in with an error when it is executed
     143             :  *
     144             :  * See |class nsGetInterface| for an example.
     145             :  */
     146       36629 : class MOZ_STACK_CLASS nsCOMPtr_helper
     147             : {
     148             : public:
     149             :   virtual nsresult NS_FASTCALL operator()(const nsIID&, void**) const = 0;
     150             : };
     151             : 
     152             : /*
     153             :  * nsQueryInterface could have been implemented as an nsCOMPtr_helper to avoid
     154             :  * adding specialized machinery in nsCOMPtr, but do_QueryInterface is called
     155             :  * often enough that the codesize savings are big enough to warrant the
     156             :  * specialcasing.
     157             :  */
     158             : class MOZ_STACK_CLASS nsQueryInterface final
     159             : {
     160             : public:
     161             :   explicit
     162      482875 :   nsQueryInterface(nsISupports* aRawPtr) : mRawPtr(aRawPtr) {}
     163             : 
     164             :   nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
     165             : 
     166             : private:
     167             :   nsISupports* MOZ_OWNING_REF mRawPtr;
     168             : };
     169             : 
     170             : class nsQueryInterfaceWithError final
     171             : {
     172             : public:
     173        6384 :   nsQueryInterfaceWithError(nsISupports* aRawPtr, nsresult* aError)
     174        6384 :     : mRawPtr(aRawPtr)
     175        6384 :     , mErrorPtr(aError)
     176             :   {
     177        6384 :   }
     178             : 
     179             :   nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
     180             : 
     181             : private:
     182             :   nsISupports* MOZ_OWNING_REF mRawPtr;
     183             :   nsresult* mErrorPtr;
     184             : };
     185             : 
     186             : inline nsQueryInterface
     187      479174 : do_QueryInterface(nsISupports* aRawPtr)
     188             : {
     189      479174 :   return nsQueryInterface(aRawPtr);
     190             : }
     191             : 
     192             : inline nsQueryInterfaceWithError
     193        6384 : do_QueryInterface(nsISupports* aRawPtr, nsresult* aError)
     194             : {
     195        6384 :   return nsQueryInterfaceWithError(aRawPtr, aError);
     196             : }
     197             : 
     198             : template<class T>
     199             : inline void
     200             : do_QueryInterface(already_AddRefed<T>&)
     201             : {
     202             :   // This signature exists solely to _stop_ you from doing the bad thing.
     203             :   // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
     204             :   // someone else is an automatic leak. See bug 8221.
     205             : }
     206             : 
     207             : template<class T>
     208             : inline void
     209             : do_QueryInterface(already_AddRefed<T>&, nsresult*)
     210             : {
     211             :   // This signature exists solely to _stop_ you from doing the bad thing.
     212             :   // Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
     213             :   // someone else is an automatic leak. See bug 8221.
     214             : }
     215             : 
     216             : 
     217             : ////////////////////////////////////////////////////////////////////////////
     218             : // Using servicemanager with COMPtrs
     219             : class nsGetServiceByCID final
     220             : {
     221             : public:
     222          15 :   explicit nsGetServiceByCID(const nsCID& aCID) : mCID(aCID) {}
     223             : 
     224             :   nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
     225             : 
     226             : private:
     227             :   const nsCID& mCID;
     228             : };
     229             : 
     230             : class nsGetServiceByCIDWithError final
     231             : {
     232             : public:
     233          77 :   nsGetServiceByCIDWithError(const nsCID& aCID, nsresult* aErrorPtr)
     234          77 :     : mCID(aCID)
     235          77 :     , mErrorPtr(aErrorPtr)
     236             :   {
     237          77 :   }
     238             : 
     239             :   nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
     240             : 
     241             : private:
     242             :   const nsCID& mCID;
     243             :   nsresult* mErrorPtr;
     244             : };
     245             : 
     246             : class nsGetServiceByContractID final
     247             : {
     248             : public:
     249        3701 :   explicit nsGetServiceByContractID(const char* aContractID)
     250        3701 :     : mContractID(aContractID)
     251             :   {
     252        3701 :   }
     253             : 
     254             :   nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
     255             : 
     256             : private:
     257             :   const char* mContractID;
     258             : };
     259             : 
     260             : class nsGetServiceByContractIDWithError final
     261             : {
     262             : public:
     263         555 :   nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
     264         555 :     : mContractID(aContractID)
     265         555 :     , mErrorPtr(aErrorPtr)
     266             :   {
     267         555 :   }
     268             : 
     269             :   nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
     270             : 
     271             : private:
     272             :   const char* mContractID;
     273             :   nsresult* mErrorPtr;
     274             : };
     275             : 
     276             : /**
     277             :  * Factors implementation for all template versions of nsCOMPtr.
     278             :  *
     279             :  * Here's the way people normally do things like this:
     280             :  *
     281             :  *   template<class T> class Foo { ... };
     282             :  *   template<> class Foo<void*> { ... };
     283             :  *   template<class T> class Foo<T*> : private Foo<void*> { ... };
     284             :  */
     285             : class nsCOMPtr_base
     286             : {
     287             : public:
     288       43296 :   explicit nsCOMPtr_base(nsISupports* aRawPtr = nullptr) : mRawPtr(aRawPtr) {}
     289             : 
     290       27122 :   NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base()
     291       27122 :   {
     292       27122 :     NSCAP_LOG_RELEASE(this, mRawPtr);
     293       27122 :     if (mRawPtr) {
     294        7853 :       NSCAP_RELEASE(this, mRawPtr);
     295             :     }
     296       27122 :   }
     297             : 
     298             :   void NS_FASTCALL
     299             :   assign_with_AddRef(nsISupports*);
     300             :   void NS_FASTCALL
     301             :   assign_from_qi(const nsQueryInterface, const nsIID&);
     302             :   void NS_FASTCALL
     303             :   assign_from_qi_with_error(const nsQueryInterfaceWithError&, const nsIID&);
     304             :   void NS_FASTCALL
     305             :   assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
     306             :   void NS_FASTCALL
     307             :   assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&, const nsIID&);
     308             :   void NS_FASTCALL
     309             :   assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
     310             :   void NS_FASTCALL
     311             :   assign_from_gs_contractid_with_error(const nsGetServiceByContractIDWithError&,
     312             :                                        const nsIID&);
     313             :   void NS_FASTCALL
     314             :   assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
     315             :   void** NS_FASTCALL
     316             :   begin_assignment();
     317             : 
     318             : protected:
     319             :   NS_MAY_ALIAS_PTR(nsISupports) MOZ_OWNING_REF mRawPtr;
     320             : 
     321       30136 :   void assign_assuming_AddRef(nsISupports* aNewPtr)
     322             :   {
     323             :     // |AddRef()|ing the new value (before entering this function) before
     324             :     // |Release()|ing the old lets us safely ignore the self-assignment case.
     325             :     // We must, however, be careful only to |Release()| _after_ doing the
     326             :     // assignment, in case the |Release()| leads to our _own_ destruction,
     327             :     // which would, in turn, cause an incorrect second |Release()| of our old
     328             :     // pointer. Thank <waterson@netscape.com> for discovering this.
     329       30136 :     nsISupports* oldPtr = mRawPtr;
     330       30136 :     mRawPtr = aNewPtr;
     331       30136 :     NSCAP_LOG_ASSIGNMENT(this, aNewPtr);
     332       30136 :     NSCAP_LOG_RELEASE(this, oldPtr);
     333       30136 :     if (oldPtr) {
     334        2549 :       NSCAP_RELEASE(this, oldPtr);
     335             :     }
     336       30136 :   }
     337             : };
     338             : 
     339             : // template<class T> class nsGetterAddRefs;
     340             : 
     341             : // Helper for assert_validity method
     342             : template<class T>
     343             : char (&TestForIID(decltype(&NS_GET_TEMPLATE_IID(T))))[2];
     344             : template<class T>
     345             : char TestForIID(...);
     346             : 
     347             : template<class T>
     348             : class nsCOMPtr final
     349             : #ifdef NSCAP_FEATURE_USE_BASE
     350             :   : private nsCOMPtr_base
     351             : #endif
     352             : {
     353             : 
     354             : #ifdef NSCAP_FEATURE_USE_BASE
     355             :   #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
     356             : #else
     357             :   #define NSCAP_CTOR_BASE(x) mRawPtr(x)
     358             : 
     359             : private:
     360             :   void assign_with_AddRef(nsISupports*);
     361             :   void assign_from_qi(const nsQueryInterface, const nsIID&);
     362             :   void assign_from_qi_with_error(const nsQueryInterfaceWithError&, const nsIID&);
     363             :   void assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
     364             :   void assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&,
     365             :                                      const nsIID&);
     366             :   void assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
     367             :   void assign_from_gs_contractid_with_error(
     368             :     const nsGetServiceByContractIDWithError&, const nsIID&);
     369             :   void assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
     370             :   void** begin_assignment();
     371             : 
     372      812111 :   void assign_assuming_AddRef(T* aNewPtr)
     373             :   {
     374      812111 :     T* oldPtr = mRawPtr;
     375      812111 :     mRawPtr = aNewPtr;
     376      812111 :     NSCAP_LOG_ASSIGNMENT(this, aNewPtr);
     377      812113 :     NSCAP_LOG_RELEASE(this, oldPtr);
     378      812113 :     if (oldPtr) {
     379       33767 :       NSCAP_RELEASE(this, oldPtr);
     380             :     }
     381      812113 :   }
     382             : 
     383             : private:
     384             :   T* MOZ_OWNING_REF mRawPtr;
     385             : #endif
     386             : 
     387     1165866 :   void assert_validity()
     388             :   {
     389             :     static_assert(1 < sizeof(TestForIID<T>(nullptr)), "nsCOMPtr only works "
     390             :                   "for types with IIDs.  Either use RefPtr; add an IID to "
     391             :                   "your type with NS_DECLARE_STATIC_IID_ACCESSOR/"
     392             :                   "NS_DEFINE_STATIC_IID_ACCESSOR; or make the nsCOMPtr point "
     393             :                   "to a base class with an IID.");
     394     1165866 :   }
     395             : 
     396             : public:
     397             :   typedef T element_type;
     398             : 
     399             : #ifndef NSCAP_FEATURE_USE_BASE
     400     1071326 :   ~nsCOMPtr()
     401             :   {
     402     1071326 :     NSCAP_LOG_RELEASE(this, mRawPtr);
     403     1071344 :     if (mRawPtr) {
     404      663623 :       NSCAP_RELEASE(this, mRawPtr);
     405             :     }
     406     1071348 :   }
     407             : #endif
     408             : 
     409             : #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
     410      699973 :   void Assert_NoQueryNeeded()
     411             :   {
     412      699973 :     if (mRawPtr) {
     413      766420 :       nsCOMPtr<T> query_result(do_QueryInterface(mRawPtr));
     414      383213 :       NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
     415             :     }
     416      699981 :   }
     417             : 
     418             :   #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
     419             : #else
     420             :   #define NSCAP_ASSERT_NO_QUERY_NEEDED()
     421             : #endif
     422             : 
     423             : 
     424             :   // Constructors
     425             : 
     426      304899 :   nsCOMPtr()
     427      304899 :     : NSCAP_CTOR_BASE(nullptr)
     428             :   {
     429      304899 :     assert_validity();
     430             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     431      304899 :   }
     432             : 
     433       36180 :   MOZ_IMPLICIT nsCOMPtr(decltype(nullptr))
     434       36180 :     : NSCAP_CTOR_BASE(nullptr)
     435             :   {
     436       36180 :     assert_validity();
     437             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     438       36180 :   }
     439             : 
     440       19402 :   nsCOMPtr(const nsCOMPtr<T>& aSmartPtr)
     441       19402 :     : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
     442             :   {
     443       19402 :     assert_validity();
     444       19402 :     if (mRawPtr) {
     445       13221 :       NSCAP_ADDREF(this, mRawPtr);
     446             :     }
     447       19402 :     NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
     448       19402 :   }
     449             : 
     450         634 :   nsCOMPtr(nsCOMPtr<T>&& aSmartPtr)
     451         634 :     : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
     452             :   {
     453         634 :     assert_validity();
     454         634 :     aSmartPtr.mRawPtr = nullptr;
     455         634 :     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     456         634 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     457         634 :   }
     458             : 
     459      272338 :   MOZ_IMPLICIT nsCOMPtr(T* aRawPtr)
     460      272338 :     : NSCAP_CTOR_BASE(aRawPtr)
     461             :   {
     462      272338 :     assert_validity();
     463      272338 :     if (mRawPtr) {
     464      129906 :       NSCAP_ADDREF(this, mRawPtr);
     465             :     }
     466      272338 :     NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
     467      272338 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     468      272337 :   }
     469             : 
     470        4622 :   MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>& aSmartPtr)
     471        4622 :     : NSCAP_CTOR_BASE(aSmartPtr.take())
     472             :   {
     473        4622 :     assert_validity();
     474        4622 :     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     475        4622 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     476        4621 :   }
     477             : 
     478             :   // Construct from |otherComPtr.forget()|.
     479       56155 :   MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>&& aSmartPtr)
     480       56155 :     : NSCAP_CTOR_BASE(aSmartPtr.take())
     481             :   {
     482       56155 :     assert_validity();
     483       56155 :     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     484       56155 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     485       56157 :   }
     486             : 
     487             :   // Construct from |already_AddRefed|.
     488             :   template<typename U>
     489           2 :   MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>& aSmartPtr)
     490           2 :     : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
     491             :   {
     492           2 :     assert_validity();
     493             :     // But make sure that U actually inherits from T.
     494             :     static_assert(mozilla::IsBaseOf<T, U>::value,
     495             :                   "U is not a subclass of T");
     496           2 :     NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
     497           2 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     498           2 :   }
     499             : 
     500             :   // Construct from |otherComPtr.forget()|.
     501             :   template<typename U>
     502        3076 :   MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>&& aSmartPtr)
     503        3076 :     : NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
     504             :   {
     505        3076 :     assert_validity();
     506             :     // But make sure that U actually inherits from T.
     507             :     static_assert(mozilla::IsBaseOf<T, U>::value,
     508             :                   "U is not a subclass of T");
     509        3076 :     NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
     510        3076 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     511        3076 :   }
     512             : 
     513             :   // Construct from |do_QueryInterface(expr)|.
     514      453891 :   MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI)
     515      453891 :     : NSCAP_CTOR_BASE(nullptr)
     516             :   {
     517      453891 :     assert_validity();
     518             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     519      453890 :     assign_from_qi(aQI, NS_GET_TEMPLATE_IID(T));
     520      453898 :   }
     521             : 
     522             :   // Construct from |do_QueryInterface(expr, &rv)|.
     523        3288 :   MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI)
     524        3288 :     : NSCAP_CTOR_BASE(nullptr)
     525             :   {
     526        3288 :     assert_validity();
     527             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     528        3288 :     assign_from_qi_with_error(aQI, NS_GET_TEMPLATE_IID(T));
     529        3288 :   }
     530             : 
     531             :   // Construct from |do_GetService(cid_expr)|.
     532          11 :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS)
     533          11 :     : NSCAP_CTOR_BASE(nullptr)
     534             :   {
     535          11 :     assert_validity();
     536             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     537          11 :     assign_from_gs_cid(aGS, NS_GET_TEMPLATE_IID(T));
     538          11 :   }
     539             : 
     540             :   // Construct from |do_GetService(cid_expr, &rv)|.
     541          76 :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS)
     542          76 :     : NSCAP_CTOR_BASE(nullptr)
     543             :   {
     544          76 :     assert_validity();
     545             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     546          76 :     assign_from_gs_cid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
     547          76 :   }
     548             : 
     549             :   // Construct from |do_GetService(contractid_expr)|.
     550        3186 :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS)
     551        3186 :     : NSCAP_CTOR_BASE(nullptr)
     552             :   {
     553        3186 :     assert_validity();
     554             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     555        3186 :     assign_from_gs_contractid(aGS, NS_GET_TEMPLATE_IID(T));
     556        3186 :   }
     557             : 
     558             :   // Construct from |do_GetService(contractid_expr, &rv)|.
     559         455 :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS)
     560         455 :     : NSCAP_CTOR_BASE(nullptr)
     561             :   {
     562         455 :     assert_validity();
     563             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     564         455 :     assign_from_gs_contractid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
     565         455 :   }
     566             : 
     567             :   // And finally, anything else we might need to construct from can exploit the
     568             :   // nsCOMPtr_helper facility.
     569        7631 :   MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
     570        7631 :     : NSCAP_CTOR_BASE(nullptr)
     571             :   {
     572        7631 :     assert_validity();
     573             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     574        7631 :     assign_from_helper(aHelper, NS_GET_TEMPLATE_IID(T));
     575        7631 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     576        7631 :   }
     577             : 
     578             :   // Defined in OwningNonNull.h
     579             :   template<class U>
     580             :   MOZ_IMPLICIT nsCOMPtr(const mozilla::OwningNonNull<U>& aOther);
     581             : 
     582             : 
     583             :   // Assignment operators
     584             : 
     585       19223 :   nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs)
     586             :   {
     587       19223 :     assign_with_AddRef(aRhs.mRawPtr);
     588       19223 :     return *this;
     589             :   }
     590             : 
     591      132362 :   nsCOMPtr<T>& operator=(T* aRhs)
     592             :   {
     593      132362 :     assign_with_AddRef(aRhs);
     594      132362 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     595      132362 :     return *this;
     596             :   }
     597             : 
     598       35227 :   nsCOMPtr<T>& operator=(decltype(nullptr))
     599             :   {
     600       35227 :     assign_assuming_AddRef(nullptr);
     601       35227 :     return *this;
     602             :   }
     603             : 
     604             :   // Assign from |already_AddRefed|.
     605             :   template<typename U>
     606          43 :   nsCOMPtr<T>& operator=(already_AddRefed<U>& aRhs)
     607             :   {
     608             :     // Make sure that U actually inherits from T
     609             :     static_assert(mozilla::IsBaseOf<T, U>::value,
     610             :                   "U is not a subclass of T");
     611          43 :     assign_assuming_AddRef(static_cast<T*>(aRhs.take()));
     612          43 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     613          43 :     return *this;
     614             :   }
     615             : 
     616             :   // Assign from |otherComPtr.forget()|.
     617             :   template<typename U>
     618       31693 :   nsCOMPtr<T>& operator=(already_AddRefed<U>&& aRhs)
     619             :   {
     620             :     // Make sure that U actually inherits from T
     621             :     static_assert(mozilla::IsBaseOf<T, U>::value,
     622             :                   "U is not a subclass of T");
     623       31693 :     assign_assuming_AddRef(static_cast<T*>(aRhs.take()));
     624       31693 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     625       31693 :     return *this;
     626             :   }
     627             : 
     628             :   // Assign from |do_QueryInterface(expr)|.
     629       18611 :   nsCOMPtr<T>& operator=(const nsQueryInterface aRhs)
     630             :   {
     631       18611 :     assign_from_qi(aRhs, NS_GET_TEMPLATE_IID(T));
     632       18611 :     return *this;
     633             :   }
     634             : 
     635             :   // Assign from |do_QueryInterface(expr, &rv)|.
     636        3093 :   nsCOMPtr<T>& operator=(const nsQueryInterfaceWithError& aRhs)
     637             :   {
     638        3093 :     assign_from_qi_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
     639        3093 :     return *this;
     640             :   }
     641             : 
     642             :   // Assign from |do_GetService(cid_expr)|.
     643           4 :   nsCOMPtr<T>& operator=(const nsGetServiceByCID aRhs)
     644             :   {
     645           4 :     assign_from_gs_cid(aRhs, NS_GET_TEMPLATE_IID(T));
     646           4 :     return *this;
     647             :   }
     648             : 
     649             :   // Assign from |do_GetService(cid_expr, &rv)|.
     650           1 :   nsCOMPtr<T>& operator=(const nsGetServiceByCIDWithError& aRhs)
     651             :   {
     652           1 :     assign_from_gs_cid_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
     653           1 :     return *this;
     654             :   }
     655             : 
     656             :   // Assign from |do_GetService(contractid_expr)|.
     657         471 :   nsCOMPtr<T>& operator=(const nsGetServiceByContractID aRhs)
     658             :   {
     659         471 :     assign_from_gs_contractid(aRhs, NS_GET_TEMPLATE_IID(T));
     660         471 :     return *this;
     661             :   }
     662             : 
     663             :   // Assign from |do_GetService(contractid_expr, &rv)|.
     664          65 :   nsCOMPtr<T>& operator=(const nsGetServiceByContractIDWithError& aRhs)
     665             :   {
     666          65 :     assign_from_gs_contractid_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
     667          65 :     return *this;
     668             :   }
     669             : 
     670             :   // And finally, anything else we might need to assign from can exploit the
     671             :   // nsCOMPtr_helper facility.
     672         907 :   nsCOMPtr<T>& operator=(const nsCOMPtr_helper& aRhs)
     673             :   {
     674         907 :     assign_from_helper(aRhs, NS_GET_TEMPLATE_IID(T));
     675         907 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     676         907 :     return *this;
     677             :   }
     678             : 
     679             :   // Defined in OwningNonNull.h
     680             :   template<class U>
     681             :   nsCOMPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther);
     682             : 
     683             :   // Exchange ownership with |aRhs|; can save a pair of refcount operations.
     684        4404 :   void swap(nsCOMPtr<T>& aRhs)
     685             :   {
     686             : #ifdef NSCAP_FEATURE_USE_BASE
     687             :     nsISupports* temp = aRhs.mRawPtr;
     688             : #else
     689        4404 :     T* temp = aRhs.mRawPtr;
     690             : #endif
     691        4404 :     NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr);
     692        4404 :     NSCAP_LOG_ASSIGNMENT(this, temp);
     693        4404 :     NSCAP_LOG_RELEASE(this, mRawPtr);
     694        4404 :     NSCAP_LOG_RELEASE(&aRhs, temp);
     695        4404 :     aRhs.mRawPtr = mRawPtr;
     696        4404 :     mRawPtr = temp;
     697             :     // |aRhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
     698        4404 :   }
     699             : 
     700             :   // Exchange ownership with |aRhs|; can save a pair of refcount operations.
     701       88656 :   void swap(T*& aRhs)
     702             :   {
     703             : #ifdef NSCAP_FEATURE_USE_BASE
     704             :     nsISupports* temp = aRhs;
     705             : #else
     706       88656 :     T* temp = aRhs;
     707             : #endif
     708       88656 :     NSCAP_LOG_ASSIGNMENT(this, temp);
     709       88657 :     NSCAP_LOG_RELEASE(this, mRawPtr);
     710       88656 :     aRhs = reinterpret_cast<T*>(mRawPtr);
     711       88656 :     mRawPtr = temp;
     712       88656 :     NSCAP_ASSERT_NO_QUERY_NEEDED();
     713       88656 :   }
     714             : 
     715             : 
     716             :   // Other pointer operators
     717             : 
     718             :   // Return the value of mRawPtr and null out mRawPtr. Useful for
     719             :   // already_AddRefed return values.
     720       85520 :   already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
     721             :   {
     722       85520 :     T* temp = nullptr;
     723       85520 :     swap(temp);
     724       85522 :     return already_AddRefed<T>(temp);
     725             :   }
     726             : 
     727             :   // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
     728             :   // Useful to avoid unnecessary AddRef/Release pairs with "out" parameters
     729             :   // where aRhs bay be a T** or an I** where I is a base class of T.
     730             :   template<typename I>
     731       26881 :   void forget(I** aRhs)
     732             :   {
     733       26881 :     NS_ASSERTION(aRhs, "Null pointer passed to forget!");
     734       26881 :     NSCAP_LOG_RELEASE(this, mRawPtr);
     735       26881 :     *aRhs = get();
     736       26881 :     mRawPtr = nullptr;
     737       26881 :   }
     738             : 
     739             :   // Prefer the implicit conversion provided automatically by
     740             :   // |operator T*() const|. Use |get()| to resolve ambiguity or to get a
     741             :   // castable pointer.
     742     2062604 :   T* get() const { return reinterpret_cast<T*>(mRawPtr); }
     743             : 
     744             :   // Makes an nsCOMPtr act like its underlying raw pointer type whenever it is
     745             :   // used in a context where a raw pointer is expected. It is this operator
     746             :   // that makes an nsCOMPtr substitutable for a raw pointer.
     747             :   //
     748             :   // Prefer the implicit use of this operator to calling |get()|, except where
     749             :   // necessary to resolve ambiguity.
     750      706438 :   operator T*() const & { return get(); }
     751             : 
     752             :   // Don't allow implicit conversion of temporary nsCOMPtr to raw pointer,
     753             :   // because the refcount might be one and the pointer will immediately become
     754             :   // invalid.
     755             :   operator T*() const && = delete;
     756             : 
     757             :   // Needed to avoid the deleted operator above
     758     2005054 :   explicit operator bool() const { return !!mRawPtr; }
     759             : 
     760      387392 :   T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
     761             :   {
     762      387392 :     MOZ_ASSERT(mRawPtr != nullptr,
     763             :                "You can't dereference a NULL nsCOMPtr with operator->().");
     764      387392 :     return get();
     765             :   }
     766             : 
     767             :   // These are not intended to be used by clients. See |address_of| below.
     768       74104 :   nsCOMPtr<T>* get_address() { return this; }
     769             :   const nsCOMPtr<T>* get_address() const { return this; }
     770             : 
     771             : public:
     772         346 :   T& operator*() const
     773             :   {
     774         346 :     MOZ_ASSERT(mRawPtr != nullptr,
     775             :                "You can't dereference a NULL nsCOMPtr with operator*().");
     776         346 :     return *get();
     777             :   }
     778             : 
     779      101865 :   T** StartAssignment()
     780             :   {
     781             : #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
     782      101865 :     return reinterpret_cast<T**>(begin_assignment());
     783             : #else
     784             :     assign_assuming_AddRef(nullptr);
     785             :     return reinterpret_cast<T**>(&mRawPtr);
     786             : #endif
     787             :   }
     788             : };
     789             : 
     790             : 
     791             : /*
     792             :  * Specializing nsCOMPtr for nsISupports allows us to use nsCOMPtr<nsISupports>
     793             :  * the same way people use nsISupports* and void*, i.e., as a `catch-all'
     794             :  * pointing to any valid [XP]COM interface. Otherwise, an nsCOMPtr<nsISupports>
     795             :  * would only be able to point to the single [XP]COM-correct nsISupports
     796             :  * instance within an object; extra querying ensues. Clients need to be able to
     797             :  * pass around arbitrary interface pointers, without hassles, through
     798             :  * intermediary code that doesn't know the exact type.
     799             :  */
     800             : template<>
     801       27122 : class nsCOMPtr<nsISupports>
     802             :   : private nsCOMPtr_base
     803             : {
     804             : public:
     805             :   typedef nsISupports element_type;
     806             : 
     807             :   // Constructors
     808             : 
     809       37148 :   nsCOMPtr()
     810       37148 :     : nsCOMPtr_base(nullptr)
     811             :   {
     812             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     813       37148 :   }
     814             : 
     815          62 :   MOZ_IMPLICIT nsCOMPtr(decltype(nullptr))
     816          62 :     : nsCOMPtr_base(nullptr)
     817             :   {
     818             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     819          62 :   }
     820             : 
     821         283 :   nsCOMPtr(const nsCOMPtr<nsISupports>& aSmartPtr)
     822         283 :     : nsCOMPtr_base(aSmartPtr.mRawPtr)
     823             :   {
     824         283 :     if (mRawPtr) {
     825         262 :       NSCAP_ADDREF(this, mRawPtr);
     826             :     }
     827         283 :     NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
     828         283 :   }
     829             : 
     830        2926 :   MOZ_IMPLICIT nsCOMPtr(nsISupports* aRawPtr)
     831        2926 :     : nsCOMPtr_base(aRawPtr)
     832             :   {
     833        2926 :     if (mRawPtr) {
     834        2839 :       NSCAP_ADDREF(this, mRawPtr);
     835             :     }
     836        2926 :     NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
     837        2926 :   }
     838             : 
     839             :   // Construct from |already_AddRefed|.
     840           0 :   MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>& aSmartPtr)
     841           0 :     : nsCOMPtr_base(aSmartPtr.take())
     842             :   {
     843           0 :     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     844           0 :   }
     845             : 
     846             :   // Construct from |otherComPtr.forget()|.
     847         608 :   MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>&& aSmartPtr)
     848         608 :     : nsCOMPtr_base(aSmartPtr.take())
     849             :   {
     850         608 :     NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
     851         608 :   }
     852             : 
     853             :   // Construct from |do_QueryInterface(expr)|.
     854        2145 :   MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface aQI)
     855        2145 :     : nsCOMPtr_base(nullptr)
     856             :   {
     857             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     858        2145 :     assign_from_qi(aQI, NS_GET_IID(nsISupports));
     859        2145 :   }
     860             : 
     861             :   // Construct from |do_QueryInterface(expr, &rv)|.
     862           0 :   MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError& aQI)
     863           0 :     : nsCOMPtr_base(nullptr)
     864             :   {
     865             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     866           0 :     assign_from_qi_with_error(aQI, NS_GET_IID(nsISupports));
     867           0 :   }
     868             : 
     869             :   // Construct from |do_GetService(cid_expr)|.
     870             :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS)
     871             :     : nsCOMPtr_base(nullptr)
     872             :   {
     873             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     874             :     assign_from_gs_cid(aGS, NS_GET_IID(nsISupports));
     875             :   }
     876             : 
     877             :   // Construct from |do_GetService(cid_expr, &rv)|.
     878             :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS)
     879             :     : nsCOMPtr_base(nullptr)
     880             :   {
     881             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     882             :     assign_from_gs_cid_with_error(aGS, NS_GET_IID(nsISupports));
     883             :   }
     884             : 
     885             :   // Construct from |do_GetService(contractid_expr)|.
     886          44 :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS)
     887          44 :     : nsCOMPtr_base(nullptr)
     888             :   {
     889             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     890          44 :     assign_from_gs_contractid(aGS, NS_GET_IID(nsISupports));
     891          44 :   }
     892             : 
     893             :   // Construct from |do_GetService(contractid_expr, &rv)|.
     894          19 :   MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS)
     895          19 :     : nsCOMPtr_base(nullptr)
     896             :   {
     897             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     898          19 :     assign_from_gs_contractid_with_error(aGS, NS_GET_IID(nsISupports));
     899          19 :   }
     900             : 
     901             :   // And finally, anything else we might need to construct from can exploit
     902             :   // the |nsCOMPtr_helper| facility
     903          61 :   MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
     904          61 :     : nsCOMPtr_base(nullptr)
     905             :   {
     906             :     NSCAP_LOG_ASSIGNMENT(this, nullptr);
     907          61 :     assign_from_helper(aHelper, NS_GET_IID(nsISupports));
     908          61 :   }
     909             : 
     910             : 
     911             :   // Assignment operators
     912             : 
     913        3649 :   nsCOMPtr<nsISupports>& operator=(const nsCOMPtr<nsISupports>& aRhs)
     914             :   {
     915        3649 :     assign_with_AddRef(aRhs.mRawPtr);
     916        3649 :     return *this;
     917             :   }
     918             : 
     919        2673 :   nsCOMPtr<nsISupports>& operator=(nsISupports* aRhs)
     920             :   {
     921        2673 :     assign_with_AddRef(aRhs);
     922        2673 :     return *this;
     923             :   }
     924             : 
     925        2695 :   nsCOMPtr<nsISupports>& operator=(decltype(nullptr))
     926             :   {
     927        2695 :     assign_assuming_AddRef(nullptr);
     928        2695 :     return *this;
     929             :   }
     930             : 
     931             :   // Assign from |already_AddRefed|.
     932        5721 :   nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>& aRhs)
     933             :   {
     934        5721 :     assign_assuming_AddRef(aRhs.take());
     935        5721 :     return *this;
     936             :   }
     937             : 
     938             :   // Assign from |otherComPtr.forget()|.
     939         348 :   nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>&& aRhs)
     940             :   {
     941         348 :     assign_assuming_AddRef(aRhs.take());
     942         348 :     return *this;
     943             :   }
     944             : 
     945             :   // Assign from |do_QueryInterface(expr)|.
     946        8278 :   nsCOMPtr<nsISupports>& operator=(const nsQueryInterface aRhs)
     947             :   {
     948        8278 :     assign_from_qi(aRhs, NS_GET_IID(nsISupports));
     949        8278 :     return *this;
     950             :   }
     951             : 
     952             :   // Assign from |do_QueryInterface(expr, &rv)|.
     953           0 :   nsCOMPtr<nsISupports>& operator=(const nsQueryInterfaceWithError& aRhs)
     954             :   {
     955           0 :     assign_from_qi_with_error(aRhs, NS_GET_IID(nsISupports));
     956           0 :     return *this;
     957             :   }
     958             : 
     959             :   // Assign from |do_GetService(cid_expr)|.
     960             :   nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCID aRhs)
     961             :   {
     962             :     assign_from_gs_cid(aRhs, NS_GET_IID(nsISupports));
     963             :     return *this;
     964             :   }
     965             : 
     966             :   // Assign from |do_GetService(cid_expr, &rv)|.
     967             :   nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCIDWithError& aRhs)
     968             :   {
     969             :     assign_from_gs_cid_with_error(aRhs, NS_GET_IID(nsISupports));
     970             :     return *this;
     971             :   }
     972             : 
     973             :   // Assign from |do_GetService(contractid_expr)|.
     974             :   nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractID aRhs)
     975             :   {
     976             :     assign_from_gs_contractid(aRhs, NS_GET_IID(nsISupports));
     977             :     return *this;
     978             :   }
     979             : 
     980             :   // Assign from |do_GetService(contractid_expr, &rv)|.
     981          13 :   nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractIDWithError& aRhs)
     982             :   {
     983          13 :     assign_from_gs_contractid_with_error(aRhs, NS_GET_IID(nsISupports));
     984          14 :     return *this;
     985             :   }
     986             : 
     987             :   // And finally, anything else we might need to assign from can exploit the
     988             :   // nsCOMPtr_helper facility
     989         151 :   nsCOMPtr<nsISupports>& operator=(const nsCOMPtr_helper& aRhs)
     990             :   {
     991         151 :     assign_from_helper(aRhs, NS_GET_IID(nsISupports));
     992         151 :     return *this;
     993             :   }
     994             : 
     995             :   // Exchange ownership with |aRhs|; can save a pair of refcount operations.
     996           0 :   void swap(nsCOMPtr<nsISupports>& aRhs)
     997             :   {
     998           0 :     nsISupports* temp = aRhs.mRawPtr;
     999           0 :     NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr);
    1000           0 :     NSCAP_LOG_ASSIGNMENT(this, temp);
    1001           0 :     NSCAP_LOG_RELEASE(this, mRawPtr);
    1002           0 :     NSCAP_LOG_RELEASE(&aRhs, temp);
    1003           0 :     aRhs.mRawPtr = mRawPtr;
    1004           0 :     mRawPtr = temp;
    1005           0 :   }
    1006             : 
    1007             :   // Exchange ownership with |aRhs|; can save a pair of refcount operations.
    1008        6611 :   void swap(nsISupports*& aRhs)
    1009             :   {
    1010        6611 :     nsISupports* temp = aRhs;
    1011        6611 :     NSCAP_LOG_ASSIGNMENT(this, temp);
    1012        6611 :     NSCAP_LOG_RELEASE(this, mRawPtr);
    1013        6611 :     aRhs = mRawPtr;
    1014        6611 :     mRawPtr = temp;
    1015        6611 :   }
    1016             : 
    1017             :   // Return the value of mRawPtr and null out mRawPtr. Useful for
    1018             :   // already_AddRefed return values.
    1019        6611 :   already_AddRefed<nsISupports> forget()
    1020             :   {
    1021        6611 :     nsISupports* temp = nullptr;
    1022        6611 :     swap(temp);
    1023        6611 :     return already_AddRefed<nsISupports>(temp);
    1024             :   }
    1025             : 
    1026             :   // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
    1027             :   // Useful to avoid unnecessary AddRef/Release pairs with "out"
    1028             :   // parameters.
    1029           0 :   void forget(nsISupports** aRhs)
    1030             :   {
    1031           0 :     NS_ASSERTION(aRhs, "Null pointer passed to forget!");
    1032           0 :     *aRhs = nullptr;
    1033           0 :     swap(*aRhs);
    1034           0 :   }
    1035             : 
    1036             :   // Other pointer operators
    1037             : 
    1038             :   // Prefer the implicit conversion provided automatically by
    1039             :   // |operator nsISupports*() const|. Use |get()| to resolve ambiguity or to
    1040             :   // get a castable pointer.
    1041       81248 :   nsISupports* get() const { return reinterpret_cast<nsISupports*>(mRawPtr); }
    1042             : 
    1043             :   // Makes an nsCOMPtr act like its underlying raw pointer type whenever it is
    1044             :   // used in a context where a raw pointer is expected. It is this operator
    1045             :   // that makes an nsCOMPtr substitutable for a raw pointer.
    1046             :   //
    1047             :   // Prefer the implicit use of this operator to calling |get()|, except where
    1048             :   // necessary to resolve ambiguity/
    1049       60601 :   operator nsISupports* () const { return get(); }
    1050             : 
    1051        5387 :   nsISupports* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
    1052             :   {
    1053        5387 :     MOZ_ASSERT(mRawPtr != nullptr,
    1054             :                "You can't dereference a NULL nsCOMPtr with operator->().");
    1055        5387 :     return get();
    1056             :   }
    1057             : 
    1058             :   // These are not intended to be used by clients. See |address_of| below.
    1059        4114 :   nsCOMPtr<nsISupports>* get_address() { return this; }
    1060             :   const nsCOMPtr<nsISupports>* get_address() const { return this; }
    1061             : 
    1062             : public:
    1063             : 
    1064             :   nsISupports& operator*() const
    1065             :   {
    1066             :     MOZ_ASSERT(mRawPtr != nullptr,
    1067             :                "You can't dereference a NULL nsCOMPtr with operator*().");
    1068             :     return *get();
    1069             :   }
    1070             : 
    1071        4344 :   nsISupports** StartAssignment()
    1072             :   {
    1073             : #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
    1074        4344 :     return reinterpret_cast<nsISupports**>(begin_assignment());
    1075             : #else
    1076             :     assign_assuming_AddRef(nullptr);
    1077             :     return reinterpret_cast<nsISupports**>(&mRawPtr);
    1078             : #endif
    1079             :   }
    1080             : };
    1081             : 
    1082             : template<typename T>
    1083             : inline void
    1084           3 : ImplCycleCollectionUnlink(nsCOMPtr<T>& aField)
    1085             : {
    1086           3 :   aField = nullptr;
    1087           3 : }
    1088             : 
    1089             : template<typename T>
    1090             : inline void
    1091        4457 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
    1092             :                             nsCOMPtr<T>& aField,
    1093             :                             const char* aName,
    1094             :                             uint32_t aFlags = 0)
    1095             : {
    1096        4457 :   CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
    1097        4457 : }
    1098             : 
    1099             : #ifndef NSCAP_FEATURE_USE_BASE
    1100             : template<class T>
    1101             : void
    1102      151585 : nsCOMPtr<T>::assign_with_AddRef(nsISupports* aRawPtr)
    1103             : {
    1104      151585 :   if (aRawPtr) {
    1105      102986 :     NSCAP_ADDREF(this, aRawPtr);
    1106             :   }
    1107      151585 :   assign_assuming_AddRef(reinterpret_cast<T*>(aRawPtr));
    1108      151585 : }
    1109             : 
    1110             : template<class T>
    1111             : void
    1112      472507 : nsCOMPtr<T>::assign_from_qi(const nsQueryInterface aQI, const nsIID& aIID)
    1113             : {
    1114             :   void* newRawPtr;
    1115      472507 :   if (NS_FAILED(aQI(aIID, &newRawPtr))) {
    1116       40469 :     newRawPtr = nullptr;
    1117             :   }
    1118      472515 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1119      472515 : }
    1120             : 
    1121             : template<class T>
    1122             : void
    1123        6381 : nsCOMPtr<T>::assign_from_qi_with_error(const nsQueryInterfaceWithError& aQI,
    1124             :                                        const nsIID& aIID)
    1125             : {
    1126             :   void* newRawPtr;
    1127        6381 :   if (NS_FAILED(aQI(aIID, &newRawPtr))) {
    1128        1102 :     newRawPtr = nullptr;
    1129             :   }
    1130        6381 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1131        6381 : }
    1132             : 
    1133             : template<class T>
    1134             : void
    1135          15 : nsCOMPtr<T>::assign_from_gs_cid(const nsGetServiceByCID aGS, const nsIID& aIID)
    1136             : {
    1137             :   void* newRawPtr;
    1138          15 :   if (NS_FAILED(aGS(aIID, &newRawPtr))) {
    1139           0 :     newRawPtr = nullptr;
    1140             :   }
    1141          15 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1142          15 : }
    1143             : 
    1144             : template<class T>
    1145             : void
    1146          77 : nsCOMPtr<T>::assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError& aGS,
    1147             :                                            const nsIID& aIID)
    1148             : {
    1149             :   void* newRawPtr;
    1150          77 :   if (NS_FAILED(aGS(aIID, &newRawPtr))) {
    1151           0 :     newRawPtr = nullptr;
    1152             :   }
    1153          77 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1154          77 : }
    1155             : 
    1156             : template<class T>
    1157             : void
    1158        3657 : nsCOMPtr<T>::assign_from_gs_contractid(const nsGetServiceByContractID aGS,
    1159             :                                        const nsIID& aIID)
    1160             : {
    1161             :   void* newRawPtr;
    1162        3657 :   if (NS_FAILED(aGS(aIID, &newRawPtr))) {
    1163          11 :     newRawPtr = nullptr;
    1164             :   }
    1165        3657 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1166        3657 : }
    1167             : 
    1168             : template<class T>
    1169             : void
    1170         520 : nsCOMPtr<T>::assign_from_gs_contractid_with_error(
    1171             :     const nsGetServiceByContractIDWithError& aGS, const nsIID& aIID)
    1172             : {
    1173             :   void* newRawPtr;
    1174         520 :   if (NS_FAILED(aGS(aIID, &newRawPtr))) {
    1175           2 :     newRawPtr = nullptr;
    1176             :   }
    1177         520 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1178         520 : }
    1179             : 
    1180             : template<class T>
    1181             : void
    1182        8538 : nsCOMPtr<T>::assign_from_helper(const nsCOMPtr_helper& helper, const nsIID& aIID)
    1183             : {
    1184             :   void* newRawPtr;
    1185        8538 :   if (NS_FAILED(helper(aIID, &newRawPtr))) {
    1186        1653 :     newRawPtr = nullptr;
    1187             :   }
    1188        8538 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1189        8538 : }
    1190             : 
    1191             : template<class T>
    1192             : void**
    1193      101865 : nsCOMPtr<T>::begin_assignment()
    1194             : {
    1195      101865 :   assign_assuming_AddRef(nullptr);
    1196             :   union
    1197             :   {
    1198             :     T** mT;
    1199             :     void** mVoid;
    1200             :   } result;
    1201      101865 :   result.mT = &mRawPtr;
    1202      101865 :   return result.mVoid;
    1203             : }
    1204             : #endif
    1205             : 
    1206             : template<class T>
    1207             : inline nsCOMPtr<T>*
    1208       78218 : address_of(nsCOMPtr<T>& aPtr)
    1209             : {
    1210       78218 :   return aPtr.get_address();
    1211             : }
    1212             : 
    1213             : template<class T>
    1214             : inline const nsCOMPtr<T>*
    1215             : address_of(const nsCOMPtr<T>& aPtr)
    1216             : {
    1217             :   return aPtr.get_address();
    1218             : }
    1219             : 
    1220             : /**
    1221             :  * This class is designed to be used for anonymous temporary objects in the
    1222             :  * argument list of calls that return COM interface pointers, e.g.,
    1223             :  *
    1224             :  *   nsCOMPtr<IFoo> fooP;
    1225             :  *   ...->QueryInterface(iid, getter_AddRefs(fooP))
    1226             :  *
    1227             :  * DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
    1228             :  *
    1229             :  * When initialized with a |nsCOMPtr|, as in the example above, it returns
    1230             :  * a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call
    1231             :  * (|QueryInterface| in this case) can fill in.
    1232             :  *
    1233             :  * This type should be a nested class inside |nsCOMPtr<T>|.
    1234             :  */
    1235             : template<class T>
    1236             : class nsGetterAddRefs
    1237             : {
    1238             : public:
    1239      101865 :   explicit nsGetterAddRefs(nsCOMPtr<T>& aSmartPtr)
    1240      101865 :     : mTargetSmartPtr(aSmartPtr)
    1241             :   {
    1242      101865 :   }
    1243             : 
    1244             : #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
    1245      101839 :   ~nsGetterAddRefs()
    1246             :   {
    1247             : #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
    1248      101839 :     NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)),
    1249             :                          mTargetSmartPtr.get());
    1250             : #endif
    1251             : 
    1252             : #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
    1253      101838 :     mTargetSmartPtr.Assert_NoQueryNeeded();
    1254             : #endif
    1255      101839 :   }
    1256             : #endif
    1257             : 
    1258        1446 :   operator void**()
    1259             :   {
    1260        1446 :     return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
    1261             :   }
    1262             : 
    1263      100419 :   operator T**() { return mTargetSmartPtr.StartAssignment(); }
    1264           0 :   T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
    1265             : 
    1266             : private:
    1267             :   nsCOMPtr<T>& mTargetSmartPtr;
    1268             : };
    1269             : 
    1270             : 
    1271             : template<>
    1272             : class nsGetterAddRefs<nsISupports>
    1273             : {
    1274             : public:
    1275        4344 :   explicit nsGetterAddRefs(nsCOMPtr<nsISupports>& aSmartPtr)
    1276        4344 :     : mTargetSmartPtr(aSmartPtr)
    1277             :   {
    1278        4344 :   }
    1279             : 
    1280             : #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
    1281        4344 :   ~nsGetterAddRefs()
    1282        4344 :   {
    1283        4344 :     NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)),
    1284        4114 :                          mTargetSmartPtr.get());
    1285        4344 :   }
    1286             : #endif
    1287             : 
    1288        1355 :   operator void**()
    1289             :   {
    1290        1355 :     return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
    1291             :   }
    1292             : 
    1293        2989 :   operator nsISupports**() { return mTargetSmartPtr.StartAssignment(); }
    1294             :   nsISupports*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
    1295             : 
    1296             : private:
    1297             :   nsCOMPtr<nsISupports>& mTargetSmartPtr;
    1298             : };
    1299             : 
    1300             : template<class T>
    1301             : inline nsGetterAddRefs<T>
    1302      106209 : getter_AddRefs(nsCOMPtr<T>& aSmartPtr)
    1303             : {
    1304      106209 :   return nsGetterAddRefs<T>(aSmartPtr);
    1305             : }
    1306             : 
    1307             : template<class T, class DestinationType>
    1308             : inline nsresult
    1309          59 : CallQueryInterface(T* aSource, nsGetterAddRefs<DestinationType> aDestination)
    1310             : {
    1311          59 :   return CallQueryInterface(aSource,
    1312          59 :                             static_cast<DestinationType**>(aDestination));
    1313             : }
    1314             : 
    1315             : 
    1316             : // Comparing two |nsCOMPtr|s
    1317             : 
    1318             : template<class T, class U>
    1319             : inline bool
    1320       17700 : operator==(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs)
    1321             : {
    1322       17700 :   return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
    1323             : }
    1324             : 
    1325             : 
    1326             : template<class T, class U>
    1327             : inline bool
    1328       24399 : operator!=(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs)
    1329             : {
    1330       24399 :   return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
    1331             : }
    1332             : 
    1333             : 
    1334             : // Comparing an |nsCOMPtr| to a raw pointer
    1335             : 
    1336             : template<class T, class U>
    1337             : inline bool
    1338        3281 : operator==(const nsCOMPtr<T>& aLhs, const U* aRhs)
    1339             : {
    1340        3281 :   return static_cast<const T*>(aLhs.get()) == aRhs;
    1341             : }
    1342             : 
    1343             : template<class T, class U>
    1344             : inline bool
    1345        2448 : operator==(const U* aLhs, const nsCOMPtr<T>& aRhs)
    1346             : {
    1347        2448 :   return aLhs == static_cast<const T*>(aRhs.get());
    1348             : }
    1349             : 
    1350             : template<class T, class U>
    1351             : inline bool
    1352             : operator!=(const nsCOMPtr<T>& aLhs, const U* aRhs)
    1353             : {
    1354             :   return static_cast<const T*>(aLhs.get()) != aRhs;
    1355             : }
    1356             : 
    1357             : template<class T, class U>
    1358             : inline bool
    1359             : operator!=(const U* aLhs, const nsCOMPtr<T>& aRhs)
    1360             : {
    1361             :   return aLhs != static_cast<const T*>(aRhs.get());
    1362             : }
    1363             : 
    1364             : template<class T, class U>
    1365             : inline bool
    1366      153153 : operator==(const nsCOMPtr<T>& aLhs, U* aRhs)
    1367             : {
    1368      153153 :   return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
    1369             : }
    1370             : 
    1371             : template<class T, class U>
    1372             : inline bool
    1373       13937 : operator==(U* aLhs, const nsCOMPtr<T>& aRhs)
    1374             : {
    1375       13937 :   return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
    1376             : }
    1377             : 
    1378             : template<class T, class U>
    1379             : inline bool
    1380       67756 : operator!=(const nsCOMPtr<T>& aLhs, U* aRhs)
    1381             : {
    1382       67756 :   return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
    1383             : }
    1384             : 
    1385             : template<class T, class U>
    1386             : inline bool
    1387        2701 : operator!=(U* aLhs, const nsCOMPtr<T>& aRhs)
    1388             : {
    1389        2701 :   return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
    1390             : }
    1391             : 
    1392             : 
    1393             : 
    1394             : // Comparing an |nsCOMPtr| to |nullptr|
    1395             : 
    1396             : template<class T>
    1397             : inline bool
    1398        6232 : operator==(const nsCOMPtr<T>& aLhs, decltype(nullptr))
    1399             : {
    1400        6232 :   return aLhs.get() == nullptr;
    1401             : }
    1402             : 
    1403             : template<class T>
    1404             : inline bool
    1405           3 : operator==(decltype(nullptr), const nsCOMPtr<T>& aRhs)
    1406             : {
    1407           3 :   return nullptr == aRhs.get();
    1408             : }
    1409             : 
    1410             : template<class T>
    1411             : inline bool
    1412        2054 : operator!=(const nsCOMPtr<T>& aLhs, decltype(nullptr))
    1413             : {
    1414        2054 :   return aLhs.get() != nullptr;
    1415             : }
    1416             : 
    1417             : template<class T>
    1418             : inline bool
    1419        9117 : operator!=(decltype(nullptr), const nsCOMPtr<T>& aRhs)
    1420             : {
    1421        9117 :   return nullptr != aRhs.get();
    1422             : }
    1423             : 
    1424             : 
    1425             : // Comparing any two [XP]COM objects for identity
    1426             : 
    1427             : inline bool
    1428         178 : SameCOMIdentity(nsISupports* aLhs, nsISupports* aRhs)
    1429             : {
    1430         356 :   return nsCOMPtr<nsISupports>(do_QueryInterface(aLhs)) ==
    1431         534 :     nsCOMPtr<nsISupports>(do_QueryInterface(aRhs));
    1432             : }
    1433             : 
    1434             : 
    1435             : 
    1436             : template<class SourceType, class DestinationType>
    1437             : inline nsresult
    1438        4478 : CallQueryInterface(nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr)
    1439             : {
    1440        4478 :   return CallQueryInterface(aSourcePtr.get(), aDestPtr);
    1441             : }
    1442             : 
    1443             : template <class T>
    1444       27869 : RefPtr<T>::RefPtr(const nsCOMPtr_helper& aHelper)
    1445             : {
    1446             :   void* newRawPtr;
    1447       27869 :   if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
    1448        5845 :     newRawPtr = nullptr;
    1449             :   }
    1450       27869 :   mRawPtr = static_cast<T*>(newRawPtr);
    1451       27869 : }
    1452             : 
    1453             : template <class T>
    1454             : RefPtr<T>&
    1455           6 : RefPtr<T>::operator=(const nsCOMPtr_helper& aHelper)
    1456             : {
    1457             :   void* newRawPtr;
    1458           6 :   if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
    1459           0 :     newRawPtr = nullptr;
    1460             :   }
    1461           6 :   assign_assuming_AddRef(static_cast<T*>(newRawPtr));
    1462           6 :   return *this;
    1463             : }
    1464             : 
    1465             : #endif // !defined(nsCOMPtr_h___)

Generated by: LCOV version 1.13