xpcom/glue/nsISupportsImpl.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 // IWYU pragma: private, include "nsISupports.h"
     8 #ifndef nsISupportsImpl_h__
     9 #define nsISupportsImpl_h__
    11 #include "nscore.h"
    12 #include "nsISupportsBase.h"
    13 #include "nsISupportsUtils.h"
    16 #if !defined(XPCOM_GLUE_AVOID_NSPR)
    17 #include "prthread.h" /* needed for thread-safety checks */
    18 #endif // !XPCOM_GLUE_AVOID_NSPR
    20 #include "nsDebug.h"
    21 #include "nsXPCOM.h"
    22 #ifndef XPCOM_GLUE
    23 #include "mozilla/Atomics.h"
    24 #endif
    25 #include "mozilla/Attributes.h"
    26 #include "mozilla/Assertions.h"
    27 #include "mozilla/Likely.h"
    28 #include "mozilla/MacroArgs.h"
    29 #include "mozilla/MacroForEach.h"
    31 inline nsISupports*
    32 ToSupports(nsISupports* p)
    33 {
    34     return p;
    35 }
    37 inline nsISupports*
    38 ToCanonicalSupports(nsISupports* p)
    39 {
    40     return nullptr;
    41 }
    43 ////////////////////////////////////////////////////////////////////////////////
    44 // Macros to help detect thread-safety:
    46 #if (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING))) && !defined(XPCOM_GLUE_AVOID_NSPR)
    48 class nsAutoOwningThread {
    49 public:
    50     nsAutoOwningThread() { mThread = PR_GetCurrentThread(); }
    51     void *GetThread() const { return mThread; }
    53 private:
    54     void *mThread;
    55 };
    57 #define NS_DECL_OWNINGTHREAD            nsAutoOwningThread _mOwningThread;
    58 #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) \
    59   NS_CheckThreadSafe(agg->_mOwningThread.GetThread(), #_class " not thread-safe")
    60 #define NS_ASSERT_OWNINGTHREAD(_class) NS_ASSERT_OWNINGTHREAD_AGGREGATE(this, _class)
    61 #else // !DEBUG && !(NIGHTLY_BUILD && !MOZ_PROFILING)
    63 #define NS_DECL_OWNINGTHREAD            /* nothing */
    64 #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) ((void)0)
    65 #define NS_ASSERT_OWNINGTHREAD(_class)  ((void)0)
    67 #endif // DEBUG || (NIGHTLY_BUILD && !MOZ_PROFILING)
    70 // Macros for reference-count and constructor logging
    72 #ifdef NS_BUILD_REFCNT_LOGGING
    74 #define NS_LOG_ADDREF(_p, _rc, _type, _size) \
    75   NS_LogAddRef((_p), (_rc), (_type), (uint32_t) (_size))
    77 #define NS_LOG_RELEASE(_p, _rc, _type) \
    78   NS_LogRelease((_p), (_rc), (_type))
    80 // Note that the following constructor/destructor logging macros are redundant
    81 // for refcounted objects that log via the NS_LOG_ADDREF/NS_LOG_RELEASE macros.
    82 // Refcount logging is preferred.
    83 #define MOZ_COUNT_CTOR(_type)                                 \
    84 do {                                                          \
    85   NS_LogCtor((void*)this, #_type, sizeof(*this));             \
    86 } while (0)
    88 #define MOZ_COUNT_CTOR_INHERITED(_type, _base)                    \
    89 do {                                                              \
    90   NS_LogCtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
    91 } while (0)
    93 #define MOZ_COUNT_DTOR(_type)                                 \
    94 do {                                                          \
    95   NS_LogDtor((void*)this, #_type, sizeof(*this));             \
    96 } while (0)
    98 #define MOZ_COUNT_DTOR_INHERITED(_type, _base)                    \
    99 do {                                                              \
   100   NS_LogDtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
   101 } while (0)
   103 /* nsCOMPtr.h allows these macros to be defined by clients
   104  * These logging functions require dynamic_cast<void*>, so they don't
   105  * do anything useful if we don't have dynamic_cast<void*>. */
   106 #define NSCAP_LOG_ASSIGNMENT(_c, _p)                                \
   107   if (_p)                                                           \
   108     NS_LogCOMPtrAddRef((_c),static_cast<nsISupports*>(_p))
   110 #define NSCAP_LOG_RELEASE(_c, _p)                                   \
   111   if (_p)                                                           \
   112     NS_LogCOMPtrRelease((_c), static_cast<nsISupports*>(_p))
   114 #else /* !NS_BUILD_REFCNT_LOGGING */
   116 #define NS_LOG_ADDREF(_p, _rc, _type, _size)
   117 #define NS_LOG_RELEASE(_p, _rc, _type)
   118 #define MOZ_COUNT_CTOR(_type)
   119 #define MOZ_COUNT_CTOR_INHERITED(_type, _base)
   120 #define MOZ_COUNT_DTOR(_type)
   121 #define MOZ_COUNT_DTOR_INHERITED(_type, _base)
   123 #endif /* NS_BUILD_REFCNT_LOGGING */
   126 // Support for ISupports classes which interact with cycle collector.
   128 #define NS_NUMBER_OF_FLAGS_IN_REFCNT 2
   129 #define NS_IN_PURPLE_BUFFER (1 << 0)
   130 #define NS_IS_PURPLE (1 << 1)
   131 #define NS_REFCOUNT_CHANGE (1 << NS_NUMBER_OF_FLAGS_IN_REFCNT)
   132 #define NS_REFCOUNT_VALUE(_val) (_val >> NS_NUMBER_OF_FLAGS_IN_REFCNT)
   134 class nsCycleCollectingAutoRefCnt {
   136 public:
   137   nsCycleCollectingAutoRefCnt()
   138     : mRefCntAndFlags(0)
   139   {}
   141   nsCycleCollectingAutoRefCnt(uintptr_t aValue)
   142     : mRefCntAndFlags(aValue << NS_NUMBER_OF_FLAGS_IN_REFCNT)
   143   {
   144   }
   146   MOZ_ALWAYS_INLINE uintptr_t incr(nsISupports *owner)
   147   {
   148     return incr(owner, nullptr);
   149   }
   151   MOZ_ALWAYS_INLINE uintptr_t incr(void *owner, nsCycleCollectionParticipant *p)
   152   {
   153     mRefCntAndFlags += NS_REFCOUNT_CHANGE;
   154     mRefCntAndFlags &= ~NS_IS_PURPLE;
   155     // For incremental cycle collection, use the purple buffer to track objects
   156     // that have been AddRef'd.
   157     if (!IsInPurpleBuffer()) {
   158       mRefCntAndFlags |= NS_IN_PURPLE_BUFFER;
   159       // Refcount isn't zero, so Suspect won't delete anything.
   160       MOZ_ASSERT(get() > 0);
   161       NS_CycleCollectorSuspect3(owner, p, this, nullptr);
   162     }
   163     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
   164   }
   166   MOZ_ALWAYS_INLINE void stabilizeForDeletion()
   167   {
   168     // Set refcnt to 1 and mark us to be in the purple buffer.
   169     // This way decr won't call suspect again.
   170     mRefCntAndFlags = NS_REFCOUNT_CHANGE | NS_IN_PURPLE_BUFFER;
   171   }
   173   MOZ_ALWAYS_INLINE uintptr_t decr(nsISupports *owner,
   174                                    bool *shouldDelete = nullptr)
   175   {
   176     return decr(owner, nullptr, shouldDelete);
   177   }
   179   MOZ_ALWAYS_INLINE uintptr_t decr(void *owner, nsCycleCollectionParticipant *p,
   180                                    bool *shouldDelete = nullptr)
   181   {
   182     MOZ_ASSERT(get() > 0);
   183     if (!IsInPurpleBuffer()) {
   184       mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
   185       mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
   186       uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags);
   187       // Suspect may delete 'owner' and 'this'!
   188       NS_CycleCollectorSuspect3(owner, p, this, shouldDelete);
   189       return retval;
   190     }
   191     mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
   192     mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
   193     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
   194   }
   196   MOZ_ALWAYS_INLINE void RemovePurple()
   197   {
   198     MOZ_ASSERT(IsPurple(), "must be purple");
   199     mRefCntAndFlags &= ~NS_IS_PURPLE;
   200   }
   202   MOZ_ALWAYS_INLINE void RemoveFromPurpleBuffer()
   203   {
   204     MOZ_ASSERT(IsInPurpleBuffer());
   205     mRefCntAndFlags &= ~(NS_IS_PURPLE | NS_IN_PURPLE_BUFFER);
   206   }
   208   MOZ_ALWAYS_INLINE bool IsPurple() const
   209   {
   210     return !!(mRefCntAndFlags & NS_IS_PURPLE);
   211   }
   213   MOZ_ALWAYS_INLINE bool IsInPurpleBuffer() const
   214   {
   215     return !!(mRefCntAndFlags & NS_IN_PURPLE_BUFFER);
   216   }
   218   MOZ_ALWAYS_INLINE nsrefcnt get() const
   219   {
   220     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
   221   }
   223   MOZ_ALWAYS_INLINE operator nsrefcnt() const
   224   {
   225     return get();
   226   }
   228  private:
   229   uintptr_t mRefCntAndFlags;
   230 };
   232 class nsAutoRefCnt {
   234  public:
   235     nsAutoRefCnt() : mValue(0) {}
   236     nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
   238     // only support prefix increment/decrement
   239     nsrefcnt operator++() { return ++mValue; }
   240     nsrefcnt operator--() { return --mValue; }
   242     nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
   243     operator nsrefcnt() const { return mValue; }
   244     nsrefcnt get() const { return mValue; }
   246     static const bool isThreadSafe = false;
   247  private:
   248     nsrefcnt operator++(int) MOZ_DELETE;
   249     nsrefcnt operator--(int) MOZ_DELETE;
   250     nsrefcnt mValue;
   251 };
   253 #ifndef XPCOM_GLUE
   254 namespace mozilla {
   255 class ThreadSafeAutoRefCnt {
   256  public:
   257     ThreadSafeAutoRefCnt() : mValue(0) {}
   258     ThreadSafeAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
   260     // only support prefix increment/decrement
   261     MOZ_ALWAYS_INLINE nsrefcnt operator++() { return ++mValue; }
   262     MOZ_ALWAYS_INLINE nsrefcnt operator--() { return --mValue; }
   264     MOZ_ALWAYS_INLINE nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
   265     MOZ_ALWAYS_INLINE operator nsrefcnt() const { return mValue; }
   266     MOZ_ALWAYS_INLINE nsrefcnt get() const { return mValue; }
   268     static const bool isThreadSafe = true;
   269  private:
   270     nsrefcnt operator++(int) MOZ_DELETE;
   271     nsrefcnt operator--(int) MOZ_DELETE;
   272     // In theory, RelaseAcquire consistency (but no weaker) is sufficient for
   273     // the counter. Making it weaker could speed up builds on ARM (but not x86),
   274     // but could break pre-existing code that assumes sequential consistency.
   275     Atomic<nsrefcnt> mValue;
   276 };
   277 }
   278 #endif
   280 ///////////////////////////////////////////////////////////////////////////////
   282 /**
   283  * Declare the reference count variable and the implementations of the
   284  * AddRef and QueryInterface methods.
   285  */
   287 #define NS_DECL_ISUPPORTS                                                     \
   288 public:                                                                       \
   289   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
   290                             void** aInstancePtr);                             \
   291   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);                          \
   292   NS_IMETHOD_(MozExternalRefCountType) Release(void);                         \
   293 protected:                                                                    \
   294   nsAutoRefCnt mRefCnt;                                                       \
   295   NS_DECL_OWNINGTHREAD                                                        \
   296 public:
   298 #define NS_DECL_THREADSAFE_ISUPPORTS                                          \
   299 public:                                                                       \
   300   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
   301                             void** aInstancePtr);                             \
   302   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);                          \
   303   NS_IMETHOD_(MozExternalRefCountType) Release(void);                         \
   304 protected:                                                                    \
   305   ::mozilla::ThreadSafeAutoRefCnt mRefCnt;                                    \
   306   NS_DECL_OWNINGTHREAD                                                        \
   307 public:
   309 #define NS_DECL_CYCLE_COLLECTING_ISUPPORTS                                    \
   310 public:                                                                       \
   311   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
   312                             void** aInstancePtr);                             \
   313   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);                          \
   314   NS_IMETHOD_(MozExternalRefCountType) Release(void);                         \
   315   NS_IMETHOD_(void) DeleteCycleCollectable(void);                             \
   316 protected:                                                                    \
   317   nsCycleCollectingAutoRefCnt mRefCnt;                                        \
   318   NS_DECL_OWNINGTHREAD                                                        \
   319 public:
   322 ///////////////////////////////////////////////////////////////////////////////
   324 /*
   325  * Implementation of AddRef and Release for non-nsISupports (ie "native")
   326  * cycle-collected classes that use the purple buffer to avoid leaks.
   327  */
   329 #define NS_IMPL_CC_NATIVE_ADDREF_BODY(_class)                                 \
   330     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
   331     NS_ASSERT_OWNINGTHREAD(_class);                                           \
   332     nsrefcnt count =                                                          \
   333       mRefCnt.incr(static_cast<void*>(this),                                  \
   334                    _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
   335     NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                       \
   336     return count;
   338 #define NS_IMPL_CC_NATIVE_RELEASE_BODY(_class)                                \
   339     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
   340     NS_ASSERT_OWNINGTHREAD(_class);                                           \
   341     nsrefcnt count =                                                          \
   342       mRefCnt.decr(static_cast<void*>(this),                                  \
   343                    _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
   344     NS_LOG_RELEASE(this, count, #_class);                                     \
   345     return count;
   347 #define NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(_class)                        \
   348 NS_METHOD_(MozExternalRefCountType) _class::AddRef(void)                      \
   349 {                                                                             \
   350   NS_IMPL_CC_NATIVE_ADDREF_BODY(_class)                                       \
   351 }
   353 #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(_class, _last) \
   354 NS_METHOD_(MozExternalRefCountType) _class::Release(void)                        \
   355 {                                                                                \
   356     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                             \
   357     NS_ASSERT_OWNINGTHREAD(_class);                                              \
   358     bool shouldDelete = false;                                                   \
   359     nsrefcnt count =                                                             \
   360       mRefCnt.decr(static_cast<void*>(this),                                     \
   361                    _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant(),     \
   362                    &shouldDelete);                                               \
   363     NS_LOG_RELEASE(this, count, #_class);                                        \
   364     if (count == 0) {                                                            \
   365         mRefCnt.incr(static_cast<void*>(this),                                   \
   366                      _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant());  \
   367         _last;                                                                   \
   368         mRefCnt.decr(static_cast<void*>(this),                                   \
   369                      _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant());  \
   370         if (shouldDelete) {                                                      \
   371             mRefCnt.stabilizeForDeletion();                                      \
   372             DeleteCycleCollectable();                                            \
   373         }                                                                        \
   374     }                                                                            \
   375     return count;                                                                \
   376 }
   378 #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(_class)                       \
   379 NS_METHOD_(MozExternalRefCountType) _class::Release(void)                     \
   380 {                                                                             \
   381   NS_IMPL_CC_NATIVE_RELEASE_BODY(_class)                                      \
   382 }
   384 #define NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(_class)            \
   385 public:                                                                       \
   386   NS_METHOD_(MozExternalRefCountType) AddRef(void) {                          \
   387     NS_IMPL_CC_NATIVE_ADDREF_BODY(_class)                                     \
   388   }                                                                           \
   389   NS_METHOD_(MozExternalRefCountType) Release(void) {                         \
   390     NS_IMPL_CC_NATIVE_RELEASE_BODY(_class)                                    \
   391   }                                                                           \
   392 protected:                                                                    \
   393   nsCycleCollectingAutoRefCnt mRefCnt;                                        \
   394   NS_DECL_OWNINGTHREAD                                                        \
   395 public:
   398 ///////////////////////////////////////////////////////////////////////////////
   400 /**
   401  * Previously used to initialize the reference count, but no longer needed.
   402  *
   403  * DEPRECATED.
   404  */
   405 #define NS_INIT_ISUPPORTS() ((void)0)
   407 /**
   408  * Use this macro to declare and implement the AddRef & Release methods for a
   409  * given non-XPCOM <i>_class</i>.
   410  *
   411  * @param _class The name of the class implementing the method
   412  */
   413 #define NS_INLINE_DECL_REFCOUNTING(_class)                                    \
   414 public:                                                                       \
   415   NS_METHOD_(MozExternalRefCountType) AddRef(void) {                          \
   416     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
   417     NS_ASSERT_OWNINGTHREAD(_class);                                           \
   418     ++mRefCnt;                                                                \
   419     NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));                     \
   420     return mRefCnt;                                                           \
   421   }                                                                           \
   422   NS_METHOD_(MozExternalRefCountType) Release(void) {                         \
   423     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
   424     NS_ASSERT_OWNINGTHREAD(_class);                                           \
   425     --mRefCnt;                                                                \
   426     NS_LOG_RELEASE(this, mRefCnt, #_class);                                   \
   427     if (mRefCnt == 0) {                                                       \
   428       NS_ASSERT_OWNINGTHREAD(_class);                                         \
   429       mRefCnt = 1; /* stabilize */                                            \
   430       delete this;                                                            \
   431       return 0;                                                               \
   432     }                                                                         \
   433     return mRefCnt;                                                           \
   434   }                                                                           \
   435 protected:                                                                    \
   436   nsAutoRefCnt mRefCnt;                                                       \
   437   NS_DECL_OWNINGTHREAD                                                        \
   438 public:
   440 /**
   441  * Use this macro to declare and implement the AddRef & Release methods for a
   442  * given non-XPCOM <i>_class</i> in a threadsafe manner.
   443  *
   444  * DOES NOT DO REFCOUNT STABILIZATION!
   445  *
   446  * @param _class The name of the class implementing the method
   447  */
   448 #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class)                         \
   449 public:                                                                       \
   450   NS_METHOD_(MozExternalRefCountType) AddRef(void) {                          \
   451     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
   452     nsrefcnt count = ++mRefCnt;                                               \
   453     NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                       \
   454     return (nsrefcnt) count;                                                  \
   455   }                                                                           \
   456   NS_METHOD_(MozExternalRefCountType) Release(void) {                         \
   457     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
   458     nsrefcnt count = --mRefCnt;                                               \
   459     NS_LOG_RELEASE(this, count, #_class);                                     \
   460     if (count == 0) {                                                         \
   461       delete (this);                                                          \
   462       return 0;                                                               \
   463     }                                                                         \
   464     return count;                                                             \
   465   }                                                                           \
   466 protected:                                                                    \
   467   ::mozilla::ThreadSafeAutoRefCnt mRefCnt;                                    \
   468 public:
   470 /**
   471  * Use this macro to implement the AddRef method for a given <i>_class</i>
   472  * @param _class The name of the class implementing the method
   473  */
   474 #define NS_IMPL_ADDREF(_class)                                                \
   475 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
   476 {                                                                             \
   477   MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                        \
   478   if (!mRefCnt.isThreadSafe)                                                  \
   479     NS_ASSERT_OWNINGTHREAD(_class);                                           \
   480   nsrefcnt count = ++mRefCnt;                                                 \
   481   NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
   482   return count;                                                               \
   483 }
   485 /**
   486  * Use this macro to implement the AddRef method for a given <i>_class</i>
   487  * implemented as a wholly owned aggregated object intended to implement
   488  * interface(s) for its owner
   489  * @param _class The name of the class implementing the method
   490  * @param _aggregator the owning/containing object
   491  */
   492 #define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator)                  \
   493 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
   494 {                                                                             \
   495   NS_PRECONDITION(_aggregator, "null aggregator");                            \
   496   return (_aggregator)->AddRef();                                             \
   497 }
   499 /**
   500  * Use this macro to implement the Release method for a given
   501  * <i>_class</i>.
   502  * @param _class The name of the class implementing the method
   503  * @param _destroy A statement that is executed when the object's
   504  *   refcount drops to zero.
   505  *
   506  * For example,
   507  *
   508  *   NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
   509  *
   510  * will cause
   511  *
   512  *   Destroy(this);
   513  *
   514  * to be invoked when the object's refcount drops to zero. This
   515  * allows for arbitrary teardown activity to occur (e.g., deallocation
   516  * of object allocated with placement new).
   517  */
   518 #define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy)                        \
   519 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
   520 {                                                                             \
   521   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
   522   if (!mRefCnt.isThreadSafe)                                                  \
   523     NS_ASSERT_OWNINGTHREAD(_class);                                           \
   524   nsrefcnt count = --mRefCnt;                                                 \
   525   NS_LOG_RELEASE(this, count, #_class);                                       \
   526   if (count == 0) {                                                           \
   527     if (!mRefCnt.isThreadSafe)                                                \
   528       NS_ASSERT_OWNINGTHREAD(_class);                                         \
   529     mRefCnt = 1; /* stabilize */                                              \
   530     _destroy;                                                                 \
   531     return 0;                                                                 \
   532   }                                                                           \
   533   return count;                                                               \
   534 }
   536 /**
   537  * Use this macro to implement the Release method for a given <i>_class</i>
   538  * @param _class The name of the class implementing the method
   539  *
   540  * A note on the 'stabilization' of the refcnt to one. At that point,
   541  * the object's refcount will have gone to zero. The object's
   542  * destructor may trigger code that attempts to QueryInterface() and
   543  * Release() 'this' again. Doing so will temporarily increment and
   544  * decrement the refcount. (Only a logic error would make one try to
   545  * keep a permanent hold on 'this'.)  To prevent re-entering the
   546  * destructor, we make sure that no balanced refcounting can return
   547  * the refcount to |0|.
   548  */
   549 #define NS_IMPL_RELEASE(_class) \
   550   NS_IMPL_RELEASE_WITH_DESTROY(_class, delete (this))
   552 /**
   553  * Use this macro to implement the Release method for a given <i>_class</i>
   554  * implemented as a wholly owned aggregated object intended to implement
   555  * interface(s) for its owner
   556  * @param _class The name of the class implementing the method
   557  * @param _aggregator the owning/containing object
   558  */
   559 #define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator)                 \
   560 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
   561 {                                                                             \
   562   NS_PRECONDITION(_aggregator, "null aggregator");                            \
   563   return (_aggregator)->Release();                                            \
   564 }
   567 #define NS_IMPL_CYCLE_COLLECTING_ADDREF(_class)                               \
   568 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
   569 {                                                                             \
   570   MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                        \
   571   NS_ASSERT_OWNINGTHREAD(_class);                                             \
   572   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
   573   nsrefcnt count = mRefCnt.incr(base);                                        \
   574   NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
   575   return count;                                                               \
   576 }
   578 #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy)       \
   579 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
   580 {                                                                             \
   581   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
   582   NS_ASSERT_OWNINGTHREAD(_class);                                             \
   583   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
   584   nsrefcnt count = mRefCnt.decr(base);                                        \
   585   NS_LOG_RELEASE(this, count, #_class);                                       \
   586   return count;                                                               \
   587 }                                                                             \
   588 NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                     \
   589 {                                                                             \
   590   _destroy;                                                                   \
   591 }
   593 #define NS_IMPL_CYCLE_COLLECTING_RELEASE(_class)                              \
   594   NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, delete (this))
   596 // _LAST_RELEASE can be useful when certain resources should be released
   597 // as soon as we know the object will be deleted.
   598 #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last)     \
   599 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
   600 {                                                                             \
   601   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
   602   NS_ASSERT_OWNINGTHREAD(_class);                                             \
   603   bool shouldDelete = false;                                                  \
   604   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
   605   nsrefcnt count = mRefCnt.decr(base, &shouldDelete);                         \
   606   NS_LOG_RELEASE(this, count, #_class);                                       \
   607   if (count == 0) {                                                           \
   608       mRefCnt.incr(base);                                                     \
   609       _last;                                                                  \
   610       mRefCnt.decr(base);                                                     \
   611       if (shouldDelete) {                                                     \
   612           mRefCnt.stabilizeForDeletion();                                     \
   613           DeleteCycleCollectable();                                           \
   614       }                                                                       \
   615   }                                                                           \
   616   return count;                                                               \
   617 }                                                                             \
   618 NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                     \
   619 {                                                                             \
   620   delete this;                                                                \
   621 }
   623 ///////////////////////////////////////////////////////////////////////////////
   625 /**
   626  * There are two ways of implementing QueryInterface, and we use both:
   627  *
   628  * Table-driven QueryInterface uses a static table of IID->offset mappings
   629  * and a shared helper function. Using it tends to reduce codesize and improve
   630  * runtime performance (due to processor cache hits).
   631  *
   632  * Macro-driven QueryInterface generates a QueryInterface function directly
   633  * using common macros. This is necessary if special QueryInterface features
   634  * are being used (such as tearoffs and conditional interfaces).
   635  *
   636  * These methods can be combined into a table-driven function call followed
   637  * by custom code for tearoffs and conditionals.
   638  */
   640 struct QITableEntry
   641 {
   642   const nsIID *iid;     // null indicates end of the QITableEntry array
   643   int32_t   offset;
   644 };
   646 NS_COM_GLUE nsresult NS_FASTCALL
   647 NS_TableDrivenQI(void* aThis, REFNSIID aIID,
   648                  void **aInstancePtr, const QITableEntry* entries);
   650 /**
   651  * Implement table-driven queryinterface
   652  */
   654 #define NS_INTERFACE_TABLE_HEAD(_class)                                       \
   655 NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr)      \
   656 {                                                                             \
   657   NS_ASSERTION(aInstancePtr,                                                  \
   658                "QueryInterface requires a non-NULL destination!");            \
   659   nsresult rv = NS_ERROR_FAILURE;
   661 #define NS_INTERFACE_TABLE_BEGIN                                              \
   662   static const QITableEntry table[] = {
   664 #define NS_INTERFACE_TABLE_ENTRY(_class, _interface)                          \
   665   { &_interface::COMTypeInfo<int>::kIID,                                      \
   666     int32_t(reinterpret_cast<char*>(                                          \
   667                         static_cast<_interface*>((_class*) 0x1000)) -         \
   668                reinterpret_cast<char*>((_class*) 0x1000))                     \
   669   },
   671 #define NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, _interface, _implClass)    \
   672   { &_interface::COMTypeInfo<int>::kIID,                                      \
   673     int32_t(reinterpret_cast<char*>(                                          \
   674                         static_cast<_interface*>(                             \
   675                                        static_cast<_implClass*>(              \
   676                                                       (_class*) 0x1000))) -   \
   677                reinterpret_cast<char*>((_class*) 0x1000))                     \
   678   },
   680 /*
   681  * XXX: we want to use mozilla::ArrayLength (or equivalent,
   682  * MOZ_ARRAY_LENGTH) in this condition, but some versions of GCC don't
   683  * see that the static_assert condition is actually constant in those
   684  * cases, even with constexpr support (?).
   685  */
   686 #define NS_INTERFACE_TABLE_END_WITH_PTR(_ptr)                                 \
   687   { nullptr, 0 } };                                                           \
   688   static_assert((sizeof(table)/sizeof(table[0])) > 1, "need at least 1 interface"); \
   689   rv = NS_TableDrivenQI(static_cast<void*>(_ptr),                             \
   690                         aIID, aInstancePtr, table);
   692 #define NS_INTERFACE_TABLE_END                                                \
   693   NS_INTERFACE_TABLE_END_WITH_PTR(this)
   695 #define NS_INTERFACE_TABLE_TAIL                                               \
   696   return rv;                                                                  \
   697 }
   699 #define NS_INTERFACE_TABLE_TAIL_INHERITING(_baseclass)                        \
   700   if (NS_SUCCEEDED(rv))                                                       \
   701     return rv;                                                                \
   702   return _baseclass::QueryInterface(aIID, aInstancePtr);                      \
   703 }
   705 #define NS_INTERFACE_TABLE_TAIL_USING_AGGREGATOR(_aggregator)                 \
   706   if (NS_SUCCEEDED(rv))                                                       \
   707     return rv;                                                                \
   708   NS_ASSERTION(_aggregator, "null aggregator");                               \
   709   return _aggregator->QueryInterface(aIID, aInstancePtr)                      \
   710 }
   712 /**
   713  * This implements query interface with two assumptions: First, the
   714  * class in question implements nsISupports and its own interface and
   715  * nothing else. Second, the implementation of the class's primary
   716  * inheritance chain leads to its own interface.
   717  *
   718  * @param _class The name of the class implementing the method
   719  * @param _classiiddef The name of the #define symbol that defines the IID
   720  * for the class (e.g. NS_ISUPPORTS_IID)
   721  */
   723 #define NS_IMPL_QUERY_HEAD(_class)                                            \
   724 NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr)      \
   725 {                                                                             \
   726   NS_ASSERTION(aInstancePtr,                                                  \
   727                "QueryInterface requires a non-NULL destination!");            \
   728   nsISupports* foundInterface;
   730 #define NS_IMPL_QUERY_BODY(_interface)                                        \
   731   if ( aIID.Equals(NS_GET_IID(_interface)) )                                  \
   732     foundInterface = static_cast<_interface*>(this);                          \
   733   else
   735 #define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)                 \
   736   if ( (condition) && aIID.Equals(NS_GET_IID(_interface)))                    \
   737     foundInterface = static_cast<_interface*>(this);                          \
   738   else
   740 #define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)                  \
   741   if ( aIID.Equals(NS_GET_IID(_interface)) )                                  \
   742     foundInterface = static_cast<_interface*>(                                \
   743                                     static_cast<_implClass*>(this));          \
   744   else
   746 #define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate)                 \
   747   if ( aIID.Equals(NS_GET_IID(_interface)) )                                  \
   748     foundInterface = static_cast<_interface*>(_aggregate);                    \
   749   else
   751 #define NS_IMPL_QUERY_TAIL_GUTS                                               \
   752     foundInterface = 0;                                                       \
   753   nsresult status;                                                            \
   754   if ( !foundInterface )                                                      \
   755     {                                                                         \
   756       /* nsISupports should be handled by this point. If not, fail. */        \
   757       MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsISupports)));                      \
   758       status = NS_NOINTERFACE;                                                \
   759     }                                                                         \
   760   else                                                                        \
   761     {                                                                         \
   762       NS_ADDREF(foundInterface);                                              \
   763       status = NS_OK;                                                         \
   764     }                                                                         \
   765   *aInstancePtr = foundInterface;                                             \
   766   return status;                                                              \
   767 }
   769 #define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass)                             \
   770     foundInterface = 0;                                                       \
   771   nsresult status;                                                            \
   772   if ( !foundInterface )                                                      \
   773     status = _baseclass::QueryInterface(aIID, (void**)&foundInterface);       \
   774   else                                                                        \
   775     {                                                                         \
   776       NS_ADDREF(foundInterface);                                              \
   777       status = NS_OK;                                                         \
   778     }                                                                         \
   779   *aInstancePtr = foundInterface;                                             \
   780   return status;                                                              \
   781 }
   783 #define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)                      \
   784     foundInterface = 0;                                                       \
   785   nsresult status;                                                            \
   786   if ( !foundInterface ) {                                                    \
   787     NS_ASSERTION(_aggregator, "null aggregator");                             \
   788     status = _aggregator->QueryInterface(aIID, (void**)&foundInterface);      \
   789   } else                                                                      \
   790     {                                                                         \
   791       NS_ADDREF(foundInterface);                                              \
   792       status = NS_OK;                                                         \
   793     }                                                                         \
   794   *aInstancePtr = foundInterface;                                             \
   795   return status;                                                              \
   796 }
   798 #define NS_IMPL_QUERY_TAIL(_supports_interface)                               \
   799   NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface)              \
   800   NS_IMPL_QUERY_TAIL_GUTS
   803   /*
   804     This is the new scheme.  Using this notation now will allow us to switch to
   805     a table driven mechanism when it's ready.  Note the difference between this
   806     and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism.  You must
   807     explicitly mention |nsISupports| when using the interface maps.
   808   */
   809 #define NS_INTERFACE_MAP_BEGIN(_implClass)      NS_IMPL_QUERY_HEAD(_implClass)
   810 #define NS_INTERFACE_MAP_ENTRY(_interface)      NS_IMPL_QUERY_BODY(_interface)
   811 #define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition)             \
   812   NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
   813 #define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate)              \
   814   NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
   816 #define NS_INTERFACE_MAP_END                    NS_IMPL_QUERY_TAIL_GUTS
   817 #define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass)              \
   818   NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
   819 #define NS_INTERFACE_MAP_END_INHERITING(_baseClass)                           \
   820   NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
   821 #define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator)                          \
   822   NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
   824 #define NS_INTERFACE_TABLE0(_class)                                           \
   825   NS_INTERFACE_TABLE_BEGIN                                                    \
   826     NS_INTERFACE_TABLE_ENTRY(_class, nsISupports)                             \
   827   NS_INTERFACE_TABLE_END
   829 #define NS_INTERFACE_TABLE(aClass, ...)                                       \
   830   MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__);                             \
   831   NS_INTERFACE_TABLE_BEGIN                                                    \
   832     MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__))          \
   833     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(aClass, nsISupports,                   \
   834                                        MOZ_ARG_1(__VA_ARGS__))                \
   835   NS_INTERFACE_TABLE_END
   837 #define NS_IMPL_QUERY_INTERFACE0(_class)                                      \
   838   NS_INTERFACE_TABLE_HEAD(_class)                                             \
   839   NS_INTERFACE_TABLE0(_class)                                                 \
   840   NS_INTERFACE_TABLE_TAIL
   842 #define NS_IMPL_QUERY_INTERFACE(aClass, ...)                                  \
   843   NS_INTERFACE_TABLE_HEAD(aClass)                                             \
   844   NS_INTERFACE_TABLE(aClass, __VA_ARGS__)                                     \
   845   NS_INTERFACE_TABLE_TAIL
   847 /**
   848  * Declare that you're going to inherit from something that already
   849  * implements nsISupports, but also implements an additional interface, thus
   850  * causing an ambiguity. In this case you don't need another mRefCnt, you
   851  * just need to forward the definitions to the appropriate superclass. E.g.
   852  *
   853  * class Bar : public Foo, public nsIBar {  // both provide nsISupports
   854  * public:
   855  *   NS_DECL_ISUPPORTS_INHERITED
   856  *   ...other nsIBar and Bar methods...
   857  * };
   858  */
   859 #define NS_DECL_ISUPPORTS_INHERITED                                           \
   860 public:                                                                       \
   861   NS_IMETHOD QueryInterface(REFNSIID aIID,                                    \
   862                             void** aInstancePtr);                             \
   863   NS_IMETHOD_(MozExternalRefCountType) AddRef(void);                          \
   864   NS_IMETHOD_(MozExternalRefCountType) Release(void);                         \
   866 /**
   867  * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
   868  * to implement the nsISupports methods, forwarding the invocations to a
   869  * superclass that already implements nsISupports.
   870  *
   871  * Note that I didn't make these inlined because they're virtual methods.
   872  */
   874 #define NS_IMPL_ADDREF_INHERITED(Class, Super)                                \
   875 NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void)                   \
   876 {                                                                             \
   877   nsrefcnt r = Super::AddRef();                                               \
   878   NS_LOG_ADDREF(this, r, #Class, sizeof(*this));                              \
   879   return r;                                                                   \
   880 }
   882 #define NS_IMPL_RELEASE_INHERITED(Class, Super)                               \
   883 NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void)                  \
   884 {                                                                             \
   885   nsrefcnt r = Super::Release();                                              \
   886   NS_LOG_RELEASE(this, r, #Class);                                            \
   887   return r;                                                                   \
   888 }
   890 /**
   891  * As above but not logging the addref/release; needed if the base
   892  * class might be aggregated.
   893  */
   894 #define NS_IMPL_NONLOGGING_ADDREF_INHERITED(Class, Super)                     \
   895 NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void)                   \
   896 {                                                                             \
   897   return Super::AddRef();                                                     \
   898 }
   900 #define NS_IMPL_NONLOGGING_RELEASE_INHERITED(Class, Super)                    \
   901 NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void)                  \
   902 {                                                                             \
   903   return Super::Release();                                                    \
   904 }
   906 #define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */
   908 #define NS_INTERFACE_TABLE_INHERITED(aClass, ...)                             \
   909   MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__);                             \
   910   NS_INTERFACE_TABLE_BEGIN                                                    \
   911     MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__))          \
   912   NS_INTERFACE_TABLE_END
   914 #define NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper)                    \
   915   NS_INTERFACE_TABLE_HEAD(aClass)                                             \
   916   NS_INTERFACE_TABLE_INHERITED0(aClass)                                       \
   917   NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
   919 #define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...)                \
   920   NS_INTERFACE_TABLE_HEAD(aClass)                                             \
   921   NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__)                           \
   922   NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
   924 /**
   925  * Convenience macros for implementing all nsISupports methods for
   926  * a simple class.
   927  * @param _class The name of the class implementing the method
   928  * @param _classiiddef The name of the #define symbol that defines the IID
   929  * for the class (e.g. NS_ISUPPORTS_IID)
   930  */
   932 #define NS_IMPL_ISUPPORTS0(_class)                                            \
   933   NS_IMPL_ADDREF(_class)                                                      \
   934   NS_IMPL_RELEASE(_class)                                                     \
   935   NS_IMPL_QUERY_INTERFACE0(_class)
   937 #define NS_IMPL_ISUPPORTS(aClass, ...)                                        \
   938   NS_IMPL_ADDREF(aClass)                                                      \
   939   NS_IMPL_RELEASE(aClass)                                                     \
   940   NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__)
   942 #define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper)                          \
   943     NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper)                        \
   944     NS_IMPL_ADDREF_INHERITED(aClass, aSuper)                                  \
   945     NS_IMPL_RELEASE_INHERITED(aClass, aSuper)                                 \
   947 #define NS_IMPL_ISUPPORTS_INHERITED(aClass, aSuper, ...)                      \
   948   NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, __VA_ARGS__)              \
   949   NS_IMPL_ADDREF_INHERITED(aClass, aSuper)                                    \
   950   NS_IMPL_RELEASE_INHERITED(aClass, aSuper)
   952 /*
   953  * Macro to glue together a QI that starts with an interface table
   954  * and segues into an interface map (e.g. it uses singleton classinfo
   955  * or tearoffs).
   956  */
   957 #define NS_INTERFACE_TABLE_TO_MAP_SEGUE \
   958   if (rv == NS_OK) return rv; \
   959   nsISupports* foundInterface;
   962 ///////////////////////////////////////////////////////////////////////////////
   963 /**
   964  *
   965  * Threadsafe implementations of the ISupports convenience macros.
   966  *
   967  * @note  These are not available when linking against the standalone glue,
   968  *        because the implementation requires PR_ symbols.
   969  */
   970 #define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
   972 /**
   973  * Macro to generate nsIClassInfo methods for classes which do not have
   974  * corresponding nsIFactory implementations.
   975  */
   976 #define NS_IMPL_THREADSAFE_CI(_class)                                         \
   977 NS_IMETHODIMP                                                                 \
   978 _class::GetInterfaces(uint32_t* _count, nsIID*** _array)                      \
   979 {                                                                             \
   980   return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array);                 \
   981 }                                                                             \
   982                                                                               \
   983 NS_IMETHODIMP                                                                 \
   984 _class::GetHelperForLanguage(uint32_t _language, nsISupports** _retval)       \
   985 {                                                                             \
   986   *_retval = nullptr;                                                         \
   987   return NS_OK;                                                               \
   988 }                                                                             \
   989                                                                               \
   990 NS_IMETHODIMP                                                                 \
   991 _class::GetContractID(char** _contractID)                                     \
   992 {                                                                             \
   993   *_contractID = nullptr;                                                     \
   994   return NS_OK;                                                               \
   995 }                                                                             \
   996                                                                               \
   997 NS_IMETHODIMP                                                                 \
   998 _class::GetClassDescription(char** _classDescription)                         \
   999 {                                                                             \
  1000   *_classDescription = nullptr;                                               \
  1001   return NS_OK;                                                               \
  1002 }                                                                             \
  1004 NS_IMETHODIMP                                                                 \
  1005 _class::GetClassID(nsCID** _classID)                                          \
  1006 {                                                                             \
  1007   *_classID = nullptr;                                                        \
  1008   return NS_OK;                                                               \
  1009 }                                                                             \
  1011 NS_IMETHODIMP                                                                 \
  1012 _class::GetImplementationLanguage(uint32_t* _language)                        \
  1013 {                                                                             \
  1014   *_language = nsIProgrammingLanguage::CPLUSPLUS;                             \
  1015   return NS_OK;                                                               \
  1016 }                                                                             \
  1018 NS_IMETHODIMP                                                                 \
  1019 _class::GetFlags(uint32_t* _flags)                                            \
  1020 {                                                                             \
  1021   *_flags = nsIClassInfo::THREADSAFE;                                         \
  1022   return NS_OK;                                                               \
  1023 }                                                                             \
  1025 NS_IMETHODIMP                                                                 \
  1026 _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc)                             \
  1027 {                                                                             \
  1028   return NS_ERROR_NOT_AVAILABLE;                                              \
  1031 #endif

mercurial