SpiderMonkeyInterface.h (3509B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_SpiderMonkeyInterface_h 8 #define mozilla_dom_SpiderMonkeyInterface_h 9 10 #include "js/RootingAPI.h" 11 #include "js/TracingAPI.h" 12 #include "jsapi.h" 13 14 namespace mozilla::dom { 15 16 /* 17 * Class that just handles the JSObject storage and tracing for spidermonkey 18 * interfaces 19 */ 20 struct SpiderMonkeyInterfaceObjectStorage { 21 protected: 22 JSObject* mImplObj; 23 JSObject* mWrappedObj; 24 25 SpiderMonkeyInterfaceObjectStorage() 26 : mImplObj(nullptr), mWrappedObj(nullptr) {} 27 28 SpiderMonkeyInterfaceObjectStorage( 29 SpiderMonkeyInterfaceObjectStorage&& aOther) 30 : mImplObj(aOther.mImplObj), mWrappedObj(aOther.mWrappedObj) { 31 aOther.mImplObj = nullptr; 32 aOther.mWrappedObj = nullptr; 33 } 34 35 public: 36 inline void TraceSelf(JSTracer* trc) { 37 JS::TraceRoot(trc, &mImplObj, 38 "SpiderMonkeyInterfaceObjectStorage.mImplObj"); 39 JS::TraceRoot(trc, &mWrappedObj, 40 "SpiderMonkeyInterfaceObjectStorage.mWrappedObj"); 41 } 42 43 inline bool inited() const { return !!mImplObj; } 44 45 inline bool WrapIntoNewCompartment(JSContext* cx) { 46 return JS_WrapObject( 47 cx, JS::MutableHandle<JSObject*>::fromMarkedLocation(&mWrappedObj)); 48 } 49 50 inline JSObject* Obj() const { 51 MOZ_ASSERT(inited()); 52 return mWrappedObj; 53 } 54 55 private: 56 SpiderMonkeyInterfaceObjectStorage( 57 const SpiderMonkeyInterfaceObjectStorage&) = delete; 58 }; 59 60 // A class for rooting an existing SpiderMonkey Interface struct 61 template <typename InterfaceType> 62 class MOZ_RAII SpiderMonkeyInterfaceRooter : private JS::CustomAutoRooter { 63 public: 64 template <typename CX> 65 SpiderMonkeyInterfaceRooter(const CX& cx, InterfaceType* aInterface) 66 : JS::CustomAutoRooter(cx), mInterface(aInterface) {} 67 68 virtual void trace(JSTracer* trc) override { mInterface->TraceSelf(trc); } 69 70 private: 71 SpiderMonkeyInterfaceObjectStorage* const mInterface; 72 }; 73 74 // And a specialization for dealing with nullable SpiderMonkey interfaces 75 template <typename Inner> 76 struct Nullable; 77 template <typename InterfaceType> 78 class MOZ_RAII SpiderMonkeyInterfaceRooter<Nullable<InterfaceType>> 79 : private JS::CustomAutoRooter { 80 public: 81 template <typename CX> 82 SpiderMonkeyInterfaceRooter(const CX& cx, Nullable<InterfaceType>* aInterface) 83 : JS::CustomAutoRooter(cx), mInterface(aInterface) {} 84 85 virtual void trace(JSTracer* trc) override { 86 if (!mInterface->IsNull()) { 87 mInterface->Value().TraceSelf(trc); 88 } 89 } 90 91 private: 92 Nullable<InterfaceType>* const mInterface; 93 }; 94 95 // Class for easily setting up a rooted SpiderMonkey interface object on the 96 // stack 97 template <typename InterfaceType> 98 class MOZ_RAII RootedSpiderMonkeyInterface final 99 : public InterfaceType, 100 private SpiderMonkeyInterfaceRooter<InterfaceType> { 101 public: 102 template <typename CX> 103 explicit RootedSpiderMonkeyInterface(const CX& cx) 104 : InterfaceType(), SpiderMonkeyInterfaceRooter<InterfaceType>(cx, this) {} 105 106 template <typename CX> 107 RootedSpiderMonkeyInterface(const CX& cx, JSObject* obj) 108 : InterfaceType(obj), 109 SpiderMonkeyInterfaceRooter<InterfaceType>(cx, this) {} 110 }; 111 112 } // namespace mozilla::dom 113 114 #endif /* mozilla_dom_SpiderMonkeyInterface_h */