BindingDeclarations.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. /* -*- Mode: C++; tab-width: 8; 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 file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /**
  6. * A header for declaring various things that binding implementation headers
  7. * might need. The idea is to make binding implementation headers safe to
  8. * include anywhere without running into include hell like we do with
  9. * BindingUtils.h
  10. */
  11. #ifndef mozilla_dom_BindingDeclarations_h__
  12. #define mozilla_dom_BindingDeclarations_h__
  13. #include "js/RootingAPI.h"
  14. #include "js/Value.h"
  15. #include "mozilla/Maybe.h"
  16. #include "mozilla/RootedOwningNonNull.h"
  17. #include "mozilla/RootedRefPtr.h"
  18. #include "mozilla/dom/DOMString.h"
  19. #include "nsCOMPtr.h"
  20. #include "nsStringGlue.h"
  21. #include "nsTArray.h"
  22. class nsIPrincipal;
  23. class nsWrapperCache;
  24. namespace mozilla {
  25. namespace dom {
  26. // Struct that serves as a base class for all dictionaries. Particularly useful
  27. // so we can use IsBaseOf to detect dictionary template arguments.
  28. struct DictionaryBase
  29. {
  30. protected:
  31. bool ParseJSON(JSContext* aCx, const nsAString& aJSON,
  32. JS::MutableHandle<JS::Value> aVal);
  33. bool StringifyToJSON(JSContext* aCx,
  34. JS::Handle<JSObject*> aObj,
  35. nsAString& aJSON) const;
  36. // Struct used as a way to force a dictionary constructor to not init the
  37. // dictionary (via constructing from a pointer to this class). We're putting
  38. // it here so that all the dictionaries will have access to it, but outside
  39. // code will not.
  40. struct FastDictionaryInitializer {
  41. };
  42. bool mIsAnyMemberPresent = false;
  43. private:
  44. // aString is expected to actually be an nsAString*. Should only be
  45. // called from StringifyToJSON.
  46. static bool AppendJSONToString(const char16_t* aJSONData,
  47. uint32_t aDataLength, void* aString);
  48. public:
  49. bool IsAnyMemberPresent() const
  50. {
  51. return mIsAnyMemberPresent;
  52. }
  53. };
  54. // Struct that serves as a base class for all typed arrays and array buffers and
  55. // array buffer views. Particularly useful so we can use IsBaseOf to detect
  56. // typed array/buffer/view template arguments.
  57. struct AllTypedArraysBase {
  58. };
  59. // Struct that serves as a base class for all owning unions.
  60. // Particularly useful so we can use IsBaseOf to detect owning union
  61. // template arguments.
  62. struct AllOwningUnionBase {
  63. };
  64. struct EnumEntry {
  65. const char* value;
  66. size_t length;
  67. };
  68. class MOZ_STACK_CLASS GlobalObject
  69. {
  70. public:
  71. GlobalObject(JSContext* aCx, JSObject* aObject);
  72. JSObject* Get() const
  73. {
  74. return mGlobalJSObject;
  75. }
  76. nsISupports* GetAsSupports() const;
  77. // The context that this returns is not guaranteed to be in the compartment of
  78. // the object returned from Get(), in fact it's generally in the caller's
  79. // compartment.
  80. JSContext* Context() const
  81. {
  82. return mCx;
  83. }
  84. bool Failed() const
  85. {
  86. return !Get();
  87. }
  88. // It returns the subjectPrincipal if called on the main-thread, otherwise
  89. // a nullptr is returned.
  90. nsIPrincipal* GetSubjectPrincipal() const;
  91. protected:
  92. JS::Rooted<JSObject*> mGlobalJSObject;
  93. JSContext* mCx;
  94. mutable nsISupports* MOZ_UNSAFE_REF("Valid because GlobalObject is a stack "
  95. "class, and mGlobalObject points to the "
  96. "global, so it won't be destroyed as long "
  97. "as GlobalObject lives on the stack") mGlobalObject;
  98. };
  99. // Class for representing optional arguments.
  100. template<typename T, typename InternalType>
  101. class Optional_base
  102. {
  103. public:
  104. Optional_base()
  105. {}
  106. explicit Optional_base(const T& aValue)
  107. {
  108. mImpl.emplace(aValue);
  109. }
  110. bool operator==(const Optional_base<T, InternalType>& aOther) const
  111. {
  112. return mImpl == aOther.mImpl;
  113. }
  114. template<typename T1, typename T2>
  115. explicit Optional_base(const T1& aValue1, const T2& aValue2)
  116. {
  117. mImpl.emplace(aValue1, aValue2);
  118. }
  119. bool WasPassed() const
  120. {
  121. return mImpl.isSome();
  122. }
  123. // Return InternalType here so we can work with it usefully.
  124. template<typename... Args>
  125. InternalType& Construct(Args&&... aArgs)
  126. {
  127. mImpl.emplace(Forward<Args>(aArgs)...);
  128. return *mImpl;
  129. }
  130. void Reset()
  131. {
  132. mImpl.reset();
  133. }
  134. const T& Value() const
  135. {
  136. return *mImpl;
  137. }
  138. // Return InternalType here so we can work with it usefully.
  139. InternalType& Value()
  140. {
  141. return *mImpl;
  142. }
  143. // And an explicit way to get the InternalType even if we're const.
  144. const InternalType& InternalValue() const
  145. {
  146. return *mImpl;
  147. }
  148. // If we ever decide to add conversion operators for optional arrays
  149. // like the ones Nullable has, we'll need to ensure that Maybe<> has
  150. // the boolean before the actual data.
  151. private:
  152. // Forbid copy-construction and assignment
  153. Optional_base(const Optional_base& other) = delete;
  154. const Optional_base &operator=(const Optional_base &other) = delete;
  155. protected:
  156. Maybe<InternalType> mImpl;
  157. };
  158. template<typename T>
  159. class Optional : public Optional_base<T, T>
  160. {
  161. public:
  162. Optional() :
  163. Optional_base<T, T>()
  164. {}
  165. explicit Optional(const T& aValue) :
  166. Optional_base<T, T>(aValue)
  167. {}
  168. };
  169. template<typename T>
  170. class Optional<JS::Handle<T> > :
  171. public Optional_base<JS::Handle<T>, JS::Rooted<T> >
  172. {
  173. public:
  174. Optional() :
  175. Optional_base<JS::Handle<T>, JS::Rooted<T> >()
  176. {}
  177. explicit Optional(JSContext* cx) :
  178. Optional_base<JS::Handle<T>, JS::Rooted<T> >()
  179. {
  180. this->Construct(cx);
  181. }
  182. Optional(JSContext* cx, const T& aValue) :
  183. Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
  184. {}
  185. // Override the const Value() to return the right thing so we're not
  186. // returning references to temporaries.
  187. JS::Handle<T> Value() const
  188. {
  189. return *this->mImpl;
  190. }
  191. // And we have to override the non-const one too, since we're
  192. // shadowing the one on the superclass.
  193. JS::Rooted<T>& Value()
  194. {
  195. return *this->mImpl;
  196. }
  197. };
  198. // A specialization of Optional for JSObject* to make sure that when someone
  199. // calls Construct() on it we will pre-initialized the JSObject* to nullptr so
  200. // it can be traced safely.
  201. template<>
  202. class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*>
  203. {
  204. public:
  205. Optional() :
  206. Optional_base<JSObject*, JSObject*>()
  207. {}
  208. explicit Optional(JSObject* aValue) :
  209. Optional_base<JSObject*, JSObject*>(aValue)
  210. {}
  211. // Don't allow us to have an uninitialized JSObject*
  212. JSObject*& Construct()
  213. {
  214. // The Android compiler sucks and thinks we're trying to construct
  215. // a JSObject* from an int if we don't cast here. :(
  216. return Optional_base<JSObject*, JSObject*>::Construct(
  217. static_cast<JSObject*>(nullptr));
  218. }
  219. template <class T1>
  220. JSObject*& Construct(const T1& t1)
  221. {
  222. return Optional_base<JSObject*, JSObject*>::Construct(t1);
  223. }
  224. };
  225. // A specialization of Optional for JS::Value to make sure no one ever uses it.
  226. template<>
  227. class Optional<JS::Value>
  228. {
  229. private:
  230. Optional() = delete;
  231. explicit Optional(const JS::Value& aValue) = delete;
  232. };
  233. // A specialization of Optional for NonNull that lets us get a T& from Value()
  234. template<typename U> class NonNull;
  235. template<typename T>
  236. class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> >
  237. {
  238. public:
  239. // We want our Value to actually return a non-const reference, even
  240. // if we're const. At least for things that are normally pointer
  241. // types...
  242. T& Value() const
  243. {
  244. return *this->mImpl->get();
  245. }
  246. // And we have to override the non-const one too, since we're
  247. // shadowing the one on the superclass.
  248. NonNull<T>& Value()
  249. {
  250. return *this->mImpl;
  251. }
  252. };
  253. // A specialization of Optional for OwningNonNull that lets us get a
  254. // T& from Value()
  255. template<typename T>
  256. class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> >
  257. {
  258. public:
  259. // We want our Value to actually return a non-const reference, even
  260. // if we're const. At least for things that are normally pointer
  261. // types...
  262. T& Value() const
  263. {
  264. return *this->mImpl->get();
  265. }
  266. // And we have to override the non-const one too, since we're
  267. // shadowing the one on the superclass.
  268. OwningNonNull<T>& Value()
  269. {
  270. return *this->mImpl;
  271. }
  272. };
  273. // Specialization for strings.
  274. // XXXbz we can't pull in FakeString here, because it depends on internal
  275. // strings. So we just have to forward-declare it and reimplement its
  276. // ToAStringPtr.
  277. namespace binding_detail {
  278. struct FakeString;
  279. } // namespace binding_detail
  280. template<>
  281. class Optional<nsAString>
  282. {
  283. public:
  284. Optional() : mPassed(false) {}
  285. bool WasPassed() const
  286. {
  287. return mPassed;
  288. }
  289. void operator=(const nsAString* str)
  290. {
  291. MOZ_ASSERT(str);
  292. mStr = str;
  293. mPassed = true;
  294. }
  295. // If this code ever goes away, remove the comment pointing to it in the
  296. // FakeString class in BindingUtils.h.
  297. void operator=(const binding_detail::FakeString* str)
  298. {
  299. MOZ_ASSERT(str);
  300. mStr = reinterpret_cast<const nsString*>(str);
  301. mPassed = true;
  302. }
  303. const nsAString& Value() const
  304. {
  305. MOZ_ASSERT(WasPassed());
  306. return *mStr;
  307. }
  308. private:
  309. // Forbid copy-construction and assignment
  310. Optional(const Optional& other) = delete;
  311. const Optional &operator=(const Optional &other) = delete;
  312. bool mPassed;
  313. const nsAString* mStr;
  314. };
  315. template<class T>
  316. class NonNull
  317. {
  318. public:
  319. NonNull()
  320. #ifdef DEBUG
  321. : inited(false)
  322. #endif
  323. {}
  324. // This is no worse than get() in terms of const handling.
  325. operator T&() const {
  326. MOZ_ASSERT(inited);
  327. MOZ_ASSERT(ptr, "NonNull<T> was set to null");
  328. return *ptr;
  329. }
  330. operator T*() const {
  331. MOZ_ASSERT(inited);
  332. MOZ_ASSERT(ptr, "NonNull<T> was set to null");
  333. return ptr;
  334. }
  335. void operator=(T* t) {
  336. ptr = t;
  337. MOZ_ASSERT(ptr);
  338. #ifdef DEBUG
  339. inited = true;
  340. #endif
  341. }
  342. template<typename U>
  343. void operator=(U* t) {
  344. ptr = t->ToAStringPtr();
  345. MOZ_ASSERT(ptr);
  346. #ifdef DEBUG
  347. inited = true;
  348. #endif
  349. }
  350. T** Slot() {
  351. #ifdef DEBUG
  352. inited = true;
  353. #endif
  354. return &ptr;
  355. }
  356. T* Ptr() {
  357. MOZ_ASSERT(inited);
  358. MOZ_ASSERT(ptr, "NonNull<T> was set to null");
  359. return ptr;
  360. }
  361. // Make us work with smart-ptr helpers that expect a get()
  362. T* get() const {
  363. MOZ_ASSERT(inited);
  364. MOZ_ASSERT(ptr);
  365. return ptr;
  366. }
  367. protected:
  368. T* ptr;
  369. #ifdef DEBUG
  370. bool inited;
  371. #endif
  372. };
  373. // Class for representing sequences in arguments. We use a non-auto array
  374. // because that allows us to use sequences of sequences and the like. This
  375. // needs to be fallible because web content controls the length of the array,
  376. // and can easily try to create very large lengths.
  377. template<typename T>
  378. class Sequence : public FallibleTArray<T>
  379. {
  380. public:
  381. Sequence() : FallibleTArray<T>()
  382. {}
  383. };
  384. inline nsWrapperCache*
  385. GetWrapperCache(nsWrapperCache* cache)
  386. {
  387. return cache;
  388. }
  389. inline nsWrapperCache*
  390. GetWrapperCache(void* p)
  391. {
  392. return nullptr;
  393. }
  394. // Helper template for smart pointers to resolve ambiguity between
  395. // GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
  396. template <template <typename> class SmartPtr, typename T>
  397. inline nsWrapperCache*
  398. GetWrapperCache(const SmartPtr<T>& aObject)
  399. {
  400. return GetWrapperCache(aObject.get());
  401. }
  402. struct MOZ_STACK_CLASS ParentObject {
  403. template<class T>
  404. MOZ_IMPLICIT ParentObject(T* aObject) :
  405. mObject(aObject),
  406. mWrapperCache(GetWrapperCache(aObject)),
  407. mUseXBLScope(false)
  408. {}
  409. template<class T, template<typename> class SmartPtr>
  410. MOZ_IMPLICIT ParentObject(const SmartPtr<T>& aObject) :
  411. mObject(aObject.get()),
  412. mWrapperCache(GetWrapperCache(aObject.get())),
  413. mUseXBLScope(false)
  414. {}
  415. ParentObject(nsISupports* aObject, nsWrapperCache* aCache) :
  416. mObject(aObject),
  417. mWrapperCache(aCache),
  418. mUseXBLScope(false)
  419. {}
  420. // We don't want to make this an nsCOMPtr because of performance reasons, but
  421. // it's safe because ParentObject is a stack class.
  422. nsISupports* const MOZ_NON_OWNING_REF mObject;
  423. nsWrapperCache* const mWrapperCache;
  424. bool mUseXBLScope;
  425. };
  426. namespace binding_detail {
  427. // Class for simple sequence arguments, only used internally by codegen.
  428. template<typename T>
  429. class AutoSequence : public AutoTArray<T, 16>
  430. {
  431. public:
  432. AutoSequence() : AutoTArray<T, 16>()
  433. {}
  434. // Allow converting to const sequences as needed
  435. operator const Sequence<T>&() const {
  436. return *reinterpret_cast<const Sequence<T>*>(this);
  437. }
  438. };
  439. } // namespace binding_detail
  440. // Enum to represent a system or non-system caller type.
  441. enum class CallerType : uint32_t {
  442. System,
  443. NonSystem
  444. };
  445. } // namespace dom
  446. } // namespace mozilla
  447. #endif // mozilla_dom_BindingDeclarations_h__