Backed out changeset 62f7af8fe549 (bug 1843981) for causing valgrind bustage. CLOSED...
[gecko.git] / dom / bindings / BindingDeclarations.h
blob24385c9fa57d3794de91feaa08fd85b18a38109b
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/. */
7 /**
8 * A header for declaring various things that binding implementation headers
9 * might need. The idea is to make binding implementation headers safe to
10 * include anywhere without running into include hell like we do with
11 * BindingUtils.h
13 #ifndef mozilla_dom_BindingDeclarations_h__
14 #define mozilla_dom_BindingDeclarations_h__
16 #include "js/RootingAPI.h"
17 #include "js/TypeDecls.h"
19 #include "mozilla/Maybe.h"
21 #include "mozilla/dom/DOMString.h"
23 #include "nsCOMPtr.h"
24 #include "nsString.h"
25 #include "nsTArray.h"
27 #include <type_traits>
29 #include "js/Value.h"
30 #include "mozilla/RootedOwningNonNull.h"
31 #include "mozilla/RootedRefPtr.h"
33 class nsIPrincipal;
34 class nsWrapperCache;
36 namespace mozilla {
38 class ErrorResult;
39 class OOMReporter;
40 class CopyableErrorResult;
42 namespace dom {
44 class BindingCallContext;
46 // Struct that serves as a base class for all dictionaries. Particularly useful
47 // so we can use std::is_base_of to detect dictionary template arguments.
48 struct DictionaryBase {
49 protected:
50 bool ParseJSON(JSContext* aCx, const nsAString& aJSON,
51 JS::MutableHandle<JS::Value> aVal);
53 bool StringifyToJSON(JSContext* aCx, JS::Handle<JSObject*> aObj,
54 nsAString& aJSON) const;
56 // Struct used as a way to force a dictionary constructor to not init the
57 // dictionary (via constructing from a pointer to this class). We're putting
58 // it here so that all the dictionaries will have access to it, but outside
59 // code will not.
60 struct FastDictionaryInitializer {};
62 bool mIsAnyMemberPresent = false;
64 private:
65 // aString is expected to actually be an nsAString*. Should only be
66 // called from StringifyToJSON.
67 static bool AppendJSONToString(const char16_t* aJSONData,
68 uint32_t aDataLength, void* aString);
70 public:
71 bool IsAnyMemberPresent() const { return mIsAnyMemberPresent; }
74 template <class T>
75 constexpr bool is_dom_dictionary = std::is_base_of_v<DictionaryBase, T>;
77 template <typename T>
78 inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionUnlink(
79 T& aDictionary) {
80 aDictionary.UnlinkForCC();
83 template <typename T>
84 inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
85 nsCycleCollectionTraversalCallback& aCallback, T& aDictionary,
86 const char* aName, uint32_t aFlags = 0) {
87 aDictionary.TraverseForCC(aCallback, aFlags);
90 template <typename T>
91 inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionUnlink(
92 UniquePtr<T>& aDictionary) {
93 aDictionary.reset();
96 template <typename T>
97 inline std::enable_if_t<is_dom_dictionary<T>, void> ImplCycleCollectionTraverse(
98 nsCycleCollectionTraversalCallback& aCallback, UniquePtr<T>& aDictionary,
99 const char* aName, uint32_t aFlags = 0) {
100 if (aDictionary) {
101 ImplCycleCollectionTraverse(aCallback, *aDictionary, aName, aFlags);
104 // Struct that serves as a base class for all typed arrays and array buffers and
105 // array buffer views. Particularly useful so we can use std::is_base_of to
106 // detect typed array/buffer/view template arguments.
107 struct AllTypedArraysBase {};
109 template <class T>
110 constexpr bool is_dom_typed_array = std::is_base_of_v<AllTypedArraysBase, T>;
112 // Struct that serves as a base class for all unions.
113 // Particularly useful so we can use std::is_base_of to detect union
114 // template arguments.
115 struct AllUnionBase {};
117 template <class T>
118 constexpr bool is_dom_union = std::is_base_of_v<AllUnionBase, T>;
120 // Struct that serves as a base class for all owning unions.
121 // Particularly useful so we can use std::is_base_of to detect owning union
122 // template arguments.
123 struct AllOwningUnionBase : public AllUnionBase {};
125 template <class T>
126 constexpr bool is_dom_owning_union = std::is_base_of_v<AllOwningUnionBase, T>;
128 struct UnionWithTypedArraysBase {};
130 template <class T>
131 constexpr bool is_dom_union_with_typedarray_members =
132 std::is_base_of_v<UnionWithTypedArraysBase, T>;
134 struct EnumEntry {
135 const char* value;
136 size_t length;
139 enum class CallerType : uint32_t;
141 class MOZ_STACK_CLASS GlobalObject {
142 public:
143 GlobalObject(JSContext* aCx, JSObject* aObject);
145 JSObject* Get() const { return mGlobalJSObject; }
147 nsISupports* GetAsSupports() const;
149 // The context that this returns is not guaranteed to be in the compartment of
150 // the object returned from Get(), in fact it's generally in the caller's
151 // compartment.
152 JSContext* Context() const { return mCx; }
154 bool Failed() const { return !Get(); }
156 // It returns the subjectPrincipal if called on the main-thread, otherwise
157 // a nullptr is returned.
158 nsIPrincipal* GetSubjectPrincipal() const;
160 // Get the caller type. Note that this needs to be called before anyone has
161 // had a chance to mess with the JSContext.
162 dom::CallerType CallerType() const;
164 protected:
165 JS::Rooted<JSObject*> mGlobalJSObject;
166 JSContext* mCx;
167 mutable nsISupports* MOZ_UNSAFE_REF(
168 "Valid because GlobalObject is a stack "
169 "class, and mGlobalObject points to the "
170 "global, so it won't be destroyed as long "
171 "as GlobalObject lives on the stack") mGlobalObject;
174 // Class for representing optional arguments.
175 template <typename T, typename InternalType>
176 class Optional_base {
177 public:
178 Optional_base() = default;
180 Optional_base(Optional_base&&) = default;
181 Optional_base& operator=(Optional_base&&) = default;
183 explicit Optional_base(const T& aValue) { mImpl.emplace(aValue); }
184 explicit Optional_base(T&& aValue) { mImpl.emplace(std::move(aValue)); }
186 bool operator==(const Optional_base<T, InternalType>& aOther) const {
187 return mImpl == aOther.mImpl;
190 bool operator!=(const Optional_base<T, InternalType>& aOther) const {
191 return mImpl != aOther.mImpl;
194 template <typename T1, typename T2>
195 explicit Optional_base(const T1& aValue1, const T2& aValue2) {
196 mImpl.emplace(aValue1, aValue2);
199 bool WasPassed() const { return mImpl.isSome(); }
201 // Return InternalType here so we can work with it usefully.
202 template <typename... Args>
203 InternalType& Construct(Args&&... aArgs) {
204 mImpl.emplace(std::forward<Args>(aArgs)...);
205 return *mImpl;
208 void Reset() { mImpl.reset(); }
210 const T& Value() const { return *mImpl; }
212 // Return InternalType here so we can work with it usefully.
213 InternalType& Value() { return *mImpl; }
215 // And an explicit way to get the InternalType even if we're const.
216 const InternalType& InternalValue() const { return *mImpl; }
218 // If we ever decide to add conversion operators for optional arrays
219 // like the ones Nullable has, we'll need to ensure that Maybe<> has
220 // the boolean before the actual data.
222 private:
223 // Forbid copy-construction and assignment
224 Optional_base(const Optional_base& other) = delete;
225 const Optional_base& operator=(const Optional_base& other) = delete;
227 protected:
228 Maybe<InternalType> mImpl;
231 template <typename T>
232 class Optional : public Optional_base<T, T> {
233 public:
234 MOZ_ALLOW_TEMPORARY Optional() : Optional_base<T, T>() {}
236 explicit Optional(const T& aValue) : Optional_base<T, T>(aValue) {}
237 Optional(Optional&&) = default;
240 template <typename T>
241 class Optional<JS::Handle<T>>
242 : public Optional_base<JS::Handle<T>, JS::Rooted<T>> {
243 public:
244 MOZ_ALLOW_TEMPORARY Optional()
245 : Optional_base<JS::Handle<T>, JS::Rooted<T>>() {}
247 explicit Optional(JSContext* cx)
248 : Optional_base<JS::Handle<T>, JS::Rooted<T>>() {
249 this->Construct(cx);
252 Optional(JSContext* cx, const T& aValue)
253 : Optional_base<JS::Handle<T>, JS::Rooted<T>>(cx, aValue) {}
255 // Override the const Value() to return the right thing so we're not
256 // returning references to temporaries.
257 JS::Handle<T> Value() const { return *this->mImpl; }
259 // And we have to override the non-const one too, since we're
260 // shadowing the one on the superclass.
261 JS::Rooted<T>& Value() { return *this->mImpl; }
264 // A specialization of Optional for JSObject* to make sure that when someone
265 // calls Construct() on it we will pre-initialized the JSObject* to nullptr so
266 // it can be traced safely.
267 template <>
268 class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*> {
269 public:
270 Optional() = default;
272 explicit Optional(JSObject* aValue)
273 : Optional_base<JSObject*, JSObject*>(aValue) {}
275 // Don't allow us to have an uninitialized JSObject*
276 JSObject*& Construct() {
277 // The Android compiler sucks and thinks we're trying to construct
278 // a JSObject* from an int if we don't cast here. :(
279 return Optional_base<JSObject*, JSObject*>::Construct(
280 static_cast<JSObject*>(nullptr));
283 template <class T1>
284 JSObject*& Construct(const T1& t1) {
285 return Optional_base<JSObject*, JSObject*>::Construct(t1);
289 // A specialization of Optional for JS::Value to make sure no one ever uses it.
290 template <>
291 class Optional<JS::Value> {
292 private:
293 Optional() = delete;
295 explicit Optional(const JS::Value& aValue) = delete;
298 // A specialization of Optional for NonNull that lets us get a T& from Value()
299 template <typename U>
300 class NonNull;
301 template <typename T>
302 class Optional<NonNull<T>> : public Optional_base<T, NonNull<T>> {
303 public:
304 // We want our Value to actually return a non-const reference, even
305 // if we're const. At least for things that are normally pointer
306 // types...
307 T& Value() const { return *this->mImpl->get(); }
309 // And we have to override the non-const one too, since we're
310 // shadowing the one on the superclass.
311 NonNull<T>& Value() { return *this->mImpl; }
314 // A specialization of Optional for OwningNonNull that lets us get a
315 // T& from Value()
316 template <typename T>
317 class Optional<OwningNonNull<T>> : public Optional_base<T, OwningNonNull<T>> {
318 public:
319 // We want our Value to actually return a non-const reference, even
320 // if we're const. At least for things that are normally pointer
321 // types...
322 T& Value() const { return *this->mImpl->get(); }
324 // And we have to override the non-const one too, since we're
325 // shadowing the one on the superclass.
326 OwningNonNull<T>& Value() { return *this->mImpl; }
329 // Specialization for strings.
330 // XXXbz we can't pull in FakeString here, because it depends on internal
331 // strings. So we just have to forward-declare it and reimplement its
332 // ToAStringPtr.
334 namespace binding_detail {
335 template <typename CharT>
336 struct FakeString;
337 } // namespace binding_detail
339 template <typename CharT>
340 class Optional<nsTSubstring<CharT>> {
341 using AString = nsTSubstring<CharT>;
343 public:
344 Optional() : mStr(nullptr) {}
346 bool WasPassed() const { return !!mStr; }
348 void operator=(const AString* str) {
349 MOZ_ASSERT(str);
350 mStr = str;
353 // If this code ever goes away, remove the comment pointing to it in the
354 // FakeString class in BindingUtils.h.
355 void operator=(const binding_detail::FakeString<CharT>* str) {
356 MOZ_ASSERT(str);
357 mStr = reinterpret_cast<const nsTString<CharT>*>(str);
360 const AString& Value() const {
361 MOZ_ASSERT(WasPassed());
362 return *mStr;
365 private:
366 // Forbid copy-construction and assignment
367 Optional(const Optional& other) = delete;
368 const Optional& operator=(const Optional& other) = delete;
370 const AString* mStr;
373 template <typename T>
374 inline void ImplCycleCollectionUnlink(Optional<T>& aField) {
375 if (aField.WasPassed()) {
376 ImplCycleCollectionUnlink(aField.Value());
380 template <typename T>
381 inline void ImplCycleCollectionTraverse(
382 nsCycleCollectionTraversalCallback& aCallback, Optional<T>& aField,
383 const char* aName, uint32_t aFlags = 0) {
384 if (aField.WasPassed()) {
385 ImplCycleCollectionTraverse(aCallback, aField.Value(), aName, aFlags);
389 template <class T>
390 class NonNull {
391 public:
392 NonNull()
393 #ifdef DEBUG
394 : inited(false)
395 #endif
399 // This is no worse than get() in terms of const handling.
400 operator T&() const {
401 MOZ_ASSERT(inited);
402 MOZ_ASSERT(ptr, "NonNull<T> was set to null");
403 return *ptr;
406 operator T*() const {
407 MOZ_ASSERT(inited);
408 MOZ_ASSERT(ptr, "NonNull<T> was set to null");
409 return ptr;
412 void operator=(T* t) {
413 ptr = t;
414 MOZ_ASSERT(ptr);
415 #ifdef DEBUG
416 inited = true;
417 #endif
420 template <typename U>
421 void operator=(U* t) {
422 ptr = t->ToAStringPtr();
423 MOZ_ASSERT(ptr);
424 #ifdef DEBUG
425 inited = true;
426 #endif
429 T** Slot() {
430 #ifdef DEBUG
431 inited = true;
432 #endif
433 return &ptr;
436 T* Ptr() {
437 MOZ_ASSERT(inited);
438 MOZ_ASSERT(ptr, "NonNull<T> was set to null");
439 return ptr;
442 // Make us work with smart-ptr helpers that expect a get()
443 T* get() const {
444 MOZ_ASSERT(inited);
445 MOZ_ASSERT(ptr);
446 return ptr;
449 protected:
450 // ptr is left uninitialized for optimization purposes.
451 MOZ_INIT_OUTSIDE_CTOR T* ptr;
452 #ifdef DEBUG
453 bool inited;
454 #endif
457 // Class for representing sequences in arguments. We use a non-auto array
458 // because that allows us to use sequences of sequences and the like. This
459 // needs to be fallible because web content controls the length of the array,
460 // and can easily try to create very large lengths.
461 template <typename T>
462 class Sequence : public FallibleTArray<T> {
463 public:
464 Sequence() : FallibleTArray<T>() {}
465 MOZ_IMPLICIT Sequence(FallibleTArray<T>&& aArray)
466 : FallibleTArray<T>(std::move(aArray)) {}
467 MOZ_IMPLICIT Sequence(nsTArray<T>&& aArray)
468 : FallibleTArray<T>(std::move(aArray)) {}
470 Sequence(Sequence&&) = default;
471 Sequence& operator=(Sequence&&) = default;
473 // XXX(Bug 1631461) Codegen.py must be adapted to allow making Sequence
474 // uncopyable.
475 Sequence(const Sequence& aOther) {
476 if (!this->AppendElements(aOther, fallible)) {
477 MOZ_CRASH("Out of memory");
480 Sequence& operator=(const Sequence& aOther) {
481 if (this != &aOther) {
482 this->Clear();
483 if (!this->AppendElements(aOther, fallible)) {
484 MOZ_CRASH("Out of memory");
487 return *this;
491 inline nsWrapperCache* GetWrapperCache(nsWrapperCache* cache) { return cache; }
493 inline nsWrapperCache* GetWrapperCache(void* p) { return nullptr; }
495 // Helper template for smart pointers to resolve ambiguity between
496 // GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
497 template <template <typename> class SmartPtr, typename T>
498 inline nsWrapperCache* GetWrapperCache(const SmartPtr<T>& aObject) {
499 return GetWrapperCache(aObject.get());
502 enum class ReflectionScope { Content, NAC, UAWidget };
504 struct MOZ_STACK_CLASS ParentObject {
505 template <class T>
506 MOZ_IMPLICIT ParentObject(T* aObject)
507 : mObject(ToSupports(aObject)),
508 mWrapperCache(GetWrapperCache(aObject)),
509 mReflectionScope(ReflectionScope::Content) {}
511 template <class T, template <typename> class SmartPtr>
512 MOZ_IMPLICIT ParentObject(const SmartPtr<T>& aObject)
513 : mObject(aObject.get()),
514 mWrapperCache(GetWrapperCache(aObject.get())),
515 mReflectionScope(ReflectionScope::Content) {}
517 ParentObject(nsISupports* aObject, nsWrapperCache* aCache)
518 : mObject(aObject),
519 mWrapperCache(aCache),
520 mReflectionScope(ReflectionScope::Content) {}
522 // We don't want to make this an nsCOMPtr because of performance reasons, but
523 // it's safe because ParentObject is a stack class.
524 nsISupports* const MOZ_NON_OWNING_REF mObject;
525 nsWrapperCache* const mWrapperCache;
526 ReflectionScope mReflectionScope;
529 namespace binding_detail {
531 // Class for simple sequence arguments, only used internally by codegen.
532 template <typename T>
533 class AutoSequence : public AutoTArray<T, 16> {
534 public:
535 AutoSequence() : AutoTArray<T, 16>() {}
537 // Allow converting to const sequences as needed
538 operator const Sequence<T>&() const {
539 return *reinterpret_cast<const Sequence<T>*>(this);
543 } // namespace binding_detail
545 // Enum to represent a system or non-system caller type.
546 enum class CallerType : uint32_t { System, NonSystem };
548 // A class that can be passed (by value or const reference) to indicate that the
549 // caller is always a system caller. This can be used as the type of an
550 // argument to force only system callers to call a function.
551 class SystemCallerGuarantee {
552 public:
553 operator CallerType() const { return CallerType::System; }
556 class ProtoAndIfaceCache;
557 typedef void (*CreateInterfaceObjectsMethod)(JSContext* aCx,
558 JS::Handle<JSObject*> aGlobal,
559 ProtoAndIfaceCache& aCache,
560 bool aDefineOnGlobal);
561 JS::Handle<JSObject*> GetPerInterfaceObjectHandle(
562 JSContext* aCx, size_t aSlotId, CreateInterfaceObjectsMethod aCreator,
563 bool aDefineOnGlobal);
565 } // namespace dom
566 } // namespace mozilla
568 #endif // mozilla_dom_BindingDeclarations_h__