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 mozilla_HoldDropJSObjects_h
8 #define mozilla_HoldDropJSObjects_h
9 
10 #include <type_traits>
11 #include "nsCycleCollectionNoteChild.h"
12 
13 class nsISupports;
14 class nsScriptObjectTracer;
15 class nsCycleCollectionParticipant;
16 
17 namespace JS {
18 class Zone;
19 }
20 
21 // Only HoldJSObjects and DropJSObjects should be called directly.
22 
23 namespace mozilla {
24 namespace cyclecollector {
25 
26 void HoldJSObjectsImpl(void* aHolder, nsScriptObjectTracer* aTracer,
27                        JS::Zone* aZone = nullptr);
28 void HoldJSObjectsImpl(nsISupports* aHolder);
29 void DropJSObjectsImpl(void* aHolder);
30 void DropJSObjectsImpl(nsISupports* aHolder);
31 
32 }  // namespace cyclecollector
33 
34 template <class T, bool isISupports = std::is_base_of<nsISupports, T>::value,
35           typename P = typename T::NS_CYCLE_COLLECTION_INNERCLASS>
36 struct HoldDropJSObjectsHelper {
HoldHoldDropJSObjectsHelper37   static void Hold(T* aHolder) {
38     cyclecollector::HoldJSObjectsImpl(aHolder,
39                                       NS_CYCLE_COLLECTION_PARTICIPANT(T));
40   }
DropHoldDropJSObjectsHelper41   static void Drop(T* aHolder) { cyclecollector::DropJSObjectsImpl(aHolder); }
42 };
43 
44 template <class T>
45 struct HoldDropJSObjectsHelper<T, true> {
46   static void Hold(T* aHolder) {
47     cyclecollector::HoldJSObjectsImpl(ToSupports(aHolder));
48   }
49   static void Drop(T* aHolder) {
50     cyclecollector::DropJSObjectsImpl(ToSupports(aHolder));
51   }
52 };
53 
54 /**
55   Classes that hold strong references to JS GC things such as `JSObjects` and
56   `JS::Values` (e.g. `JS::Heap<JSObject*> mFoo;`) must use these, generally by
57   calling `HoldJSObjects(this)` and `DropJSObjects(this)` in the ctor and dtor
58   respectively.
59 
60   For classes that are wrapper cached and hold no other strong references to JS
61   GC things, there's no need to call these; it will be taken care of
62   automatically by nsWrapperCache.
63 **/
64 template <class T>
65 void HoldJSObjects(T* aHolder) {
66   static_assert(!std::is_base_of<nsCycleCollectionParticipant, T>::value,
67                 "Don't call this on the CC participant but on the object that "
68                 "it's for (in an Unlink implementation it's usually stored in "
69                 "a variable named 'tmp').");
70   HoldDropJSObjectsHelper<T>::Hold(aHolder);
71 }
72 
73 template <class T>
74 void DropJSObjects(T* aHolder) {
75   static_assert(!std::is_base_of<nsCycleCollectionParticipant, T>::value,
76                 "Don't call this on the CC participant but on the object that "
77                 "it's for (in an Unlink implementation it's usually stored in "
78                 "a variable named 'tmp').");
79   HoldDropJSObjectsHelper<T>::Drop(aHolder);
80 }
81 
82 }  // namespace mozilla
83 
84 #endif  // mozilla_HoldDropJSObjects_h
85