Bug 1700051: part 36) Reduce accessibility of `SoftText::mBegin` to `private`. r...
[gecko.git] / dom / bindings / BindingDeclarations.h
blobcf60cb70b7bbd1b7026994175f453d55526d60b9
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 <typename T>
75 inline std::enable_if_t<std::is_base_of<DictionaryBase, T>::value, void>
76 ImplCycleCollectionUnlink(T& aDictionary) {
77 aDictionary.UnlinkForCC();
80 template <typename T>
81 inline std::enable_if_t<std::is_base_of<DictionaryBase, T>::value, void>
82 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
83 T& aDictionary, const char* aName,
84 uint32_t aFlags = 0) {
85 aDictionary.TraverseForCC(aCallback, aFlags);
88 // Struct that serves as a base class for all typed arrays and array buffers and
89 // array buffer views. Particularly useful so we can use std::is_base_of to
90 // detect typed array/buffer/view template arguments.
91 struct AllTypedArraysBase {};
93 // Struct that serves as a base class for all owning unions.
94 // Particularly useful so we can use std::is_base_of to detect owning union
95 // template arguments.
96 struct AllOwningUnionBase {};
98 struct EnumEntry {
99 const char* value;
100 size_t length;
103 enum class CallerType : uint32_t;
105 class MOZ_STACK_CLASS GlobalObject {
106 public:
107 GlobalObject(JSContext* aCx, JSObject* aObject);
109 JSObject* Get() const { return mGlobalJSObject; }
111 nsISupports* GetAsSupports() const;
113 // The context that this returns is not guaranteed to be in the compartment of
114 // the object returned from Get(), in fact it's generally in the caller's
115 // compartment.
116 JSContext* Context() const { return mCx; }
118 bool Failed() const { return !Get(); }
120 // It returns the subjectPrincipal if called on the main-thread, otherwise
121 // a nullptr is returned.
122 nsIPrincipal* GetSubjectPrincipal() const;
124 // Get the caller type. Note that this needs to be called before anyone has
125 // had a chance to mess with the JSContext.
126 dom::CallerType CallerType() const;
128 protected:
129 JS::Rooted<JSObject*> mGlobalJSObject;
130 JSContext* mCx;
131 mutable nsISupports* MOZ_UNSAFE_REF(
132 "Valid because GlobalObject is a stack "
133 "class, and mGlobalObject points to the "
134 "global, so it won't be destroyed as long "
135 "as GlobalObject lives on the stack") mGlobalObject;
138 // Class for representing optional arguments.
139 template <typename T, typename InternalType>
140 class Optional_base {
141 public:
142 Optional_base() = default;
144 explicit Optional_base(const T& aValue) { mImpl.emplace(aValue); }
146 bool operator==(const Optional_base<T, InternalType>& aOther) const {
147 return mImpl == aOther.mImpl;
150 bool operator!=(const Optional_base<T, InternalType>& aOther) const {
151 return mImpl != aOther.mImpl;
154 template <typename T1, typename T2>
155 explicit Optional_base(const T1& aValue1, const T2& aValue2) {
156 mImpl.emplace(aValue1, aValue2);
159 bool WasPassed() const { return mImpl.isSome(); }
161 // Return InternalType here so we can work with it usefully.
162 template <typename... Args>
163 InternalType& Construct(Args&&... aArgs) {
164 mImpl.emplace(std::forward<Args>(aArgs)...);
165 return *mImpl;
168 void Reset() { mImpl.reset(); }
170 const T& Value() const { return *mImpl; }
172 // Return InternalType here so we can work with it usefully.
173 InternalType& Value() { return *mImpl; }
175 // And an explicit way to get the InternalType even if we're const.
176 const InternalType& InternalValue() const { return *mImpl; }
178 // If we ever decide to add conversion operators for optional arrays
179 // like the ones Nullable has, we'll need to ensure that Maybe<> has
180 // the boolean before the actual data.
182 private:
183 // Forbid copy-construction and assignment
184 Optional_base(const Optional_base& other) = delete;
185 const Optional_base& operator=(const Optional_base& other) = delete;
187 protected:
188 Maybe<InternalType> mImpl;
191 template <typename T>
192 class Optional : public Optional_base<T, T> {
193 public:
194 MOZ_ALLOW_TEMPORARY Optional() : Optional_base<T, T>() {}
196 explicit Optional(const T& aValue) : Optional_base<T, T>(aValue) {}
199 template <typename T>
200 class Optional<JS::Handle<T>>
201 : public Optional_base<JS::Handle<T>, JS::Rooted<T>> {
202 public:
203 MOZ_ALLOW_TEMPORARY Optional()
204 : Optional_base<JS::Handle<T>, JS::Rooted<T>>() {}
206 explicit Optional(JSContext* cx)
207 : Optional_base<JS::Handle<T>, JS::Rooted<T>>() {
208 this->Construct(cx);
211 Optional(JSContext* cx, const T& aValue)
212 : Optional_base<JS::Handle<T>, JS::Rooted<T>>(cx, aValue) {}
214 // Override the const Value() to return the right thing so we're not
215 // returning references to temporaries.
216 JS::Handle<T> Value() const { return *this->mImpl; }
218 // And we have to override the non-const one too, since we're
219 // shadowing the one on the superclass.
220 JS::Rooted<T>& Value() { return *this->mImpl; }
223 // A specialization of Optional for JSObject* to make sure that when someone
224 // calls Construct() on it we will pre-initialized the JSObject* to nullptr so
225 // it can be traced safely.
226 template <>
227 class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*> {
228 public:
229 Optional() = default;
231 explicit Optional(JSObject* aValue)
232 : Optional_base<JSObject*, JSObject*>(aValue) {}
234 // Don't allow us to have an uninitialized JSObject*
235 JSObject*& Construct() {
236 // The Android compiler sucks and thinks we're trying to construct
237 // a JSObject* from an int if we don't cast here. :(
238 return Optional_base<JSObject*, JSObject*>::Construct(
239 static_cast<JSObject*>(nullptr));
242 template <class T1>
243 JSObject*& Construct(const T1& t1) {
244 return Optional_base<JSObject*, JSObject*>::Construct(t1);
248 // A specialization of Optional for JS::Value to make sure no one ever uses it.
249 template <>
250 class Optional<JS::Value> {
251 private:
252 Optional() = delete;
254 explicit Optional(const JS::Value& aValue) = delete;
257 // A specialization of Optional for NonNull that lets us get a T& from Value()
258 template <typename U>
259 class NonNull;
260 template <typename T>
261 class Optional<NonNull<T>> : public Optional_base<T, NonNull<T>> {
262 public:
263 // We want our Value to actually return a non-const reference, even
264 // if we're const. At least for things that are normally pointer
265 // types...
266 T& Value() const { return *this->mImpl->get(); }
268 // And we have to override the non-const one too, since we're
269 // shadowing the one on the superclass.
270 NonNull<T>& Value() { return *this->mImpl; }
273 // A specialization of Optional for OwningNonNull that lets us get a
274 // T& from Value()
275 template <typename T>
276 class Optional<OwningNonNull<T>> : public Optional_base<T, OwningNonNull<T>> {
277 public:
278 // We want our Value to actually return a non-const reference, even
279 // if we're const. At least for things that are normally pointer
280 // types...
281 T& Value() const { return *this->mImpl->get(); }
283 // And we have to override the non-const one too, since we're
284 // shadowing the one on the superclass.
285 OwningNonNull<T>& Value() { return *this->mImpl; }
288 // Specialization for strings.
289 // XXXbz we can't pull in FakeString here, because it depends on internal
290 // strings. So we just have to forward-declare it and reimplement its
291 // ToAStringPtr.
293 namespace binding_detail {
294 template <typename CharT>
295 struct FakeString;
296 } // namespace binding_detail
298 template <typename CharT>
299 class Optional<nsTSubstring<CharT>> {
300 using AString = nsTSubstring<CharT>;
302 public:
303 Optional() : mStr(nullptr) {}
305 bool WasPassed() const { return !!mStr; }
307 void operator=(const AString* str) {
308 MOZ_ASSERT(str);
309 mStr = str;
312 // If this code ever goes away, remove the comment pointing to it in the
313 // FakeString class in BindingUtils.h.
314 void operator=(const binding_detail::FakeString<CharT>* str) {
315 MOZ_ASSERT(str);
316 mStr = reinterpret_cast<const nsTString<CharT>*>(str);
319 const AString& Value() const {
320 MOZ_ASSERT(WasPassed());
321 return *mStr;
324 private:
325 // Forbid copy-construction and assignment
326 Optional(const Optional& other) = delete;
327 const Optional& operator=(const Optional& other) = delete;
329 const AString* mStr;
332 template <typename T>
333 inline void ImplCycleCollectionUnlink(Optional<T>& aField) {
334 if (aField.WasPassed()) {
335 ImplCycleCollectionUnlink(aField.Value());
339 template <typename T>
340 inline void ImplCycleCollectionTraverse(
341 nsCycleCollectionTraversalCallback& aCallback, Optional<T>& aField,
342 const char* aName, uint32_t aFlags = 0) {
343 if (aField.WasPassed()) {
344 ImplCycleCollectionTraverse(aCallback, aField.Value(), aName, aFlags);
348 template <class T>
349 class NonNull {
350 public:
351 NonNull()
352 #ifdef DEBUG
353 : inited(false)
354 #endif
358 // This is no worse than get() in terms of const handling.
359 operator T&() const {
360 MOZ_ASSERT(inited);
361 MOZ_ASSERT(ptr, "NonNull<T> was set to null");
362 return *ptr;
365 operator T*() const {
366 MOZ_ASSERT(inited);
367 MOZ_ASSERT(ptr, "NonNull<T> was set to null");
368 return ptr;
371 void operator=(T* t) {
372 ptr = t;
373 MOZ_ASSERT(ptr);
374 #ifdef DEBUG
375 inited = true;
376 #endif
379 template <typename U>
380 void operator=(U* t) {
381 ptr = t->ToAStringPtr();
382 MOZ_ASSERT(ptr);
383 #ifdef DEBUG
384 inited = true;
385 #endif
388 T** Slot() {
389 #ifdef DEBUG
390 inited = true;
391 #endif
392 return &ptr;
395 T* Ptr() {
396 MOZ_ASSERT(inited);
397 MOZ_ASSERT(ptr, "NonNull<T> was set to null");
398 return ptr;
401 // Make us work with smart-ptr helpers that expect a get()
402 T* get() const {
403 MOZ_ASSERT(inited);
404 MOZ_ASSERT(ptr);
405 return ptr;
408 protected:
409 // ptr is left uninitialized for optimization purposes.
410 MOZ_INIT_OUTSIDE_CTOR T* ptr;
411 #ifdef DEBUG
412 bool inited;
413 #endif
416 // Class for representing sequences in arguments. We use a non-auto array
417 // because that allows us to use sequences of sequences and the like. This
418 // needs to be fallible because web content controls the length of the array,
419 // and can easily try to create very large lengths.
420 template <typename T>
421 class Sequence : public FallibleTArray<T> {
422 public:
423 Sequence() : FallibleTArray<T>() {}
424 MOZ_IMPLICIT Sequence(FallibleTArray<T>&& aArray)
425 : FallibleTArray<T>(std::move(aArray)) {}
426 MOZ_IMPLICIT Sequence(nsTArray<T>&& aArray)
427 : FallibleTArray<T>(std::move(aArray)) {}
429 Sequence(Sequence&&) = default;
430 Sequence& operator=(Sequence&&) = default;
432 // XXX(Bug 1631461) Codegen.py must be adapted to allow making Sequence
433 // uncopyable.
434 Sequence(const Sequence& aOther) {
435 if (!this->AppendElements(aOther, fallible)) {
436 MOZ_CRASH("Out of memory");
439 Sequence& operator=(const Sequence& aOther) {
440 if (this != &aOther) {
441 this->Clear();
442 if (!this->AppendElements(aOther, fallible)) {
443 MOZ_CRASH("Out of memory");
446 return *this;
450 inline nsWrapperCache* GetWrapperCache(nsWrapperCache* cache) { return cache; }
452 inline nsWrapperCache* GetWrapperCache(void* p) { return nullptr; }
454 // Helper template for smart pointers to resolve ambiguity between
455 // GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
456 template <template <typename> class SmartPtr, typename T>
457 inline nsWrapperCache* GetWrapperCache(const SmartPtr<T>& aObject) {
458 return GetWrapperCache(aObject.get());
461 enum class ReflectionScope { Content, NAC, UAWidget };
463 struct MOZ_STACK_CLASS ParentObject {
464 template <class T>
465 MOZ_IMPLICIT ParentObject(T* aObject)
466 : mObject(ToSupports(aObject)),
467 mWrapperCache(GetWrapperCache(aObject)),
468 mReflectionScope(ReflectionScope::Content) {}
470 template <class T, template <typename> class SmartPtr>
471 MOZ_IMPLICIT ParentObject(const SmartPtr<T>& aObject)
472 : mObject(aObject.get()),
473 mWrapperCache(GetWrapperCache(aObject.get())),
474 mReflectionScope(ReflectionScope::Content) {}
476 ParentObject(nsISupports* aObject, nsWrapperCache* aCache)
477 : mObject(aObject),
478 mWrapperCache(aCache),
479 mReflectionScope(ReflectionScope::Content) {}
481 // We don't want to make this an nsCOMPtr because of performance reasons, but
482 // it's safe because ParentObject is a stack class.
483 nsISupports* const MOZ_NON_OWNING_REF mObject;
484 nsWrapperCache* const mWrapperCache;
485 ReflectionScope mReflectionScope;
488 namespace binding_detail {
490 // Class for simple sequence arguments, only used internally by codegen.
491 template <typename T>
492 class AutoSequence : public AutoTArray<T, 16> {
493 public:
494 AutoSequence() : AutoTArray<T, 16>() {}
496 // Allow converting to const sequences as needed
497 operator const Sequence<T>&() const {
498 return *reinterpret_cast<const Sequence<T>*>(this);
502 } // namespace binding_detail
504 // Enum to represent a system or non-system caller type.
505 enum class CallerType : uint32_t { System, NonSystem };
507 // A class that can be passed (by value or const reference) to indicate that the
508 // caller is always a system caller. This can be used as the type of an
509 // argument to force only system callers to call a function.
510 class SystemCallerGuarantee {
511 public:
512 operator CallerType() const { return CallerType::System; }
515 class ProtoAndIfaceCache;
516 typedef void (*CreateInterfaceObjectsMethod)(JSContext* aCx,
517 JS::Handle<JSObject*> aGlobal,
518 ProtoAndIfaceCache& aCache,
519 bool aDefineOnGlobal);
520 JS::Handle<JSObject*> GetPerInterfaceObjectHandle(
521 JSContext* aCx, size_t aSlotId, CreateInterfaceObjectsMethod aCreator,
522 bool aDefineOnGlobal);
524 } // namespace dom
525 } // namespace mozilla
527 #endif // mozilla_dom_BindingDeclarations_h__