123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- /**
- * A header for declaring various things that binding implementation headers
- * might need. The idea is to make binding implementation headers safe to
- * include anywhere without running into include hell like we do with
- * BindingUtils.h
- */
- #ifndef mozilla_dom_BindingDeclarations_h__
- #define mozilla_dom_BindingDeclarations_h__
- #include "js/RootingAPI.h"
- #include "js/Value.h"
- #include "mozilla/Maybe.h"
- #include "mozilla/RootedOwningNonNull.h"
- #include "mozilla/RootedRefPtr.h"
- #include "mozilla/dom/DOMString.h"
- #include "nsCOMPtr.h"
- #include "nsStringGlue.h"
- #include "nsTArray.h"
- class nsIPrincipal;
- class nsWrapperCache;
- namespace mozilla {
- namespace dom {
- // Struct that serves as a base class for all dictionaries. Particularly useful
- // so we can use IsBaseOf to detect dictionary template arguments.
- struct DictionaryBase
- {
- protected:
- bool ParseJSON(JSContext* aCx, const nsAString& aJSON,
- JS::MutableHandle<JS::Value> aVal);
- bool StringifyToJSON(JSContext* aCx,
- JS::Handle<JSObject*> aObj,
- nsAString& aJSON) const;
- // Struct used as a way to force a dictionary constructor to not init the
- // dictionary (via constructing from a pointer to this class). We're putting
- // it here so that all the dictionaries will have access to it, but outside
- // code will not.
- struct FastDictionaryInitializer {
- };
- bool mIsAnyMemberPresent = false;
- private:
- // aString is expected to actually be an nsAString*. Should only be
- // called from StringifyToJSON.
- static bool AppendJSONToString(const char16_t* aJSONData,
- uint32_t aDataLength, void* aString);
- public:
- bool IsAnyMemberPresent() const
- {
- return mIsAnyMemberPresent;
- }
- };
- // Struct that serves as a base class for all typed arrays and array buffers and
- // array buffer views. Particularly useful so we can use IsBaseOf to detect
- // typed array/buffer/view template arguments.
- struct AllTypedArraysBase {
- };
- // Struct that serves as a base class for all owning unions.
- // Particularly useful so we can use IsBaseOf to detect owning union
- // template arguments.
- struct AllOwningUnionBase {
- };
- struct EnumEntry {
- const char* value;
- size_t length;
- };
- class MOZ_STACK_CLASS GlobalObject
- {
- public:
- GlobalObject(JSContext* aCx, JSObject* aObject);
- JSObject* Get() const
- {
- return mGlobalJSObject;
- }
- nsISupports* GetAsSupports() const;
- // The context that this returns is not guaranteed to be in the compartment of
- // the object returned from Get(), in fact it's generally in the caller's
- // compartment.
- JSContext* Context() const
- {
- return mCx;
- }
- bool Failed() const
- {
- return !Get();
- }
- // It returns the subjectPrincipal if called on the main-thread, otherwise
- // a nullptr is returned.
- nsIPrincipal* GetSubjectPrincipal() const;
- protected:
- JS::Rooted<JSObject*> mGlobalJSObject;
- JSContext* mCx;
- mutable nsISupports* MOZ_UNSAFE_REF("Valid because GlobalObject is a stack "
- "class, and mGlobalObject points to the "
- "global, so it won't be destroyed as long "
- "as GlobalObject lives on the stack") mGlobalObject;
- };
- // Class for representing optional arguments.
- template<typename T, typename InternalType>
- class Optional_base
- {
- public:
- Optional_base()
- {}
- explicit Optional_base(const T& aValue)
- {
- mImpl.emplace(aValue);
- }
- bool operator==(const Optional_base<T, InternalType>& aOther) const
- {
- return mImpl == aOther.mImpl;
- }
- template<typename T1, typename T2>
- explicit Optional_base(const T1& aValue1, const T2& aValue2)
- {
- mImpl.emplace(aValue1, aValue2);
- }
- bool WasPassed() const
- {
- return mImpl.isSome();
- }
- // Return InternalType here so we can work with it usefully.
- template<typename... Args>
- InternalType& Construct(Args&&... aArgs)
- {
- mImpl.emplace(Forward<Args>(aArgs)...);
- return *mImpl;
- }
- void Reset()
- {
- mImpl.reset();
- }
- const T& Value() const
- {
- return *mImpl;
- }
- // Return InternalType here so we can work with it usefully.
- InternalType& Value()
- {
- return *mImpl;
- }
- // And an explicit way to get the InternalType even if we're const.
- const InternalType& InternalValue() const
- {
- return *mImpl;
- }
- // If we ever decide to add conversion operators for optional arrays
- // like the ones Nullable has, we'll need to ensure that Maybe<> has
- // the boolean before the actual data.
- private:
- // Forbid copy-construction and assignment
- Optional_base(const Optional_base& other) = delete;
- const Optional_base &operator=(const Optional_base &other) = delete;
- protected:
- Maybe<InternalType> mImpl;
- };
- template<typename T>
- class Optional : public Optional_base<T, T>
- {
- public:
- Optional() :
- Optional_base<T, T>()
- {}
- explicit Optional(const T& aValue) :
- Optional_base<T, T>(aValue)
- {}
- };
- template<typename T>
- class Optional<JS::Handle<T> > :
- public Optional_base<JS::Handle<T>, JS::Rooted<T> >
- {
- public:
- Optional() :
- Optional_base<JS::Handle<T>, JS::Rooted<T> >()
- {}
- explicit Optional(JSContext* cx) :
- Optional_base<JS::Handle<T>, JS::Rooted<T> >()
- {
- this->Construct(cx);
- }
- Optional(JSContext* cx, const T& aValue) :
- Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
- {}
- // Override the const Value() to return the right thing so we're not
- // returning references to temporaries.
- JS::Handle<T> Value() const
- {
- return *this->mImpl;
- }
- // And we have to override the non-const one too, since we're
- // shadowing the one on the superclass.
- JS::Rooted<T>& Value()
- {
- return *this->mImpl;
- }
- };
- // A specialization of Optional for JSObject* to make sure that when someone
- // calls Construct() on it we will pre-initialized the JSObject* to nullptr so
- // it can be traced safely.
- template<>
- class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*>
- {
- public:
- Optional() :
- Optional_base<JSObject*, JSObject*>()
- {}
- explicit Optional(JSObject* aValue) :
- Optional_base<JSObject*, JSObject*>(aValue)
- {}
- // Don't allow us to have an uninitialized JSObject*
- JSObject*& Construct()
- {
- // The Android compiler sucks and thinks we're trying to construct
- // a JSObject* from an int if we don't cast here. :(
- return Optional_base<JSObject*, JSObject*>::Construct(
- static_cast<JSObject*>(nullptr));
- }
- template <class T1>
- JSObject*& Construct(const T1& t1)
- {
- return Optional_base<JSObject*, JSObject*>::Construct(t1);
- }
- };
- // A specialization of Optional for JS::Value to make sure no one ever uses it.
- template<>
- class Optional<JS::Value>
- {
- private:
- Optional() = delete;
- explicit Optional(const JS::Value& aValue) = delete;
- };
- // A specialization of Optional for NonNull that lets us get a T& from Value()
- template<typename U> class NonNull;
- template<typename T>
- class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> >
- {
- public:
- // We want our Value to actually return a non-const reference, even
- // if we're const. At least for things that are normally pointer
- // types...
- T& Value() const
- {
- return *this->mImpl->get();
- }
- // And we have to override the non-const one too, since we're
- // shadowing the one on the superclass.
- NonNull<T>& Value()
- {
- return *this->mImpl;
- }
- };
- // A specialization of Optional for OwningNonNull that lets us get a
- // T& from Value()
- template<typename T>
- class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> >
- {
- public:
- // We want our Value to actually return a non-const reference, even
- // if we're const. At least for things that are normally pointer
- // types...
- T& Value() const
- {
- return *this->mImpl->get();
- }
- // And we have to override the non-const one too, since we're
- // shadowing the one on the superclass.
- OwningNonNull<T>& Value()
- {
- return *this->mImpl;
- }
- };
- // Specialization for strings.
- // XXXbz we can't pull in FakeString here, because it depends on internal
- // strings. So we just have to forward-declare it and reimplement its
- // ToAStringPtr.
- namespace binding_detail {
- struct FakeString;
- } // namespace binding_detail
- template<>
- class Optional<nsAString>
- {
- public:
- Optional() : mPassed(false) {}
- bool WasPassed() const
- {
- return mPassed;
- }
- void operator=(const nsAString* str)
- {
- MOZ_ASSERT(str);
- mStr = str;
- mPassed = true;
- }
- // If this code ever goes away, remove the comment pointing to it in the
- // FakeString class in BindingUtils.h.
- void operator=(const binding_detail::FakeString* str)
- {
- MOZ_ASSERT(str);
- mStr = reinterpret_cast<const nsString*>(str);
- mPassed = true;
- }
- const nsAString& Value() const
- {
- MOZ_ASSERT(WasPassed());
- return *mStr;
- }
- private:
- // Forbid copy-construction and assignment
- Optional(const Optional& other) = delete;
- const Optional &operator=(const Optional &other) = delete;
- bool mPassed;
- const nsAString* mStr;
- };
- template<class T>
- class NonNull
- {
- public:
- NonNull()
- #ifdef DEBUG
- : inited(false)
- #endif
- {}
- // This is no worse than get() in terms of const handling.
- operator T&() const {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr, "NonNull<T> was set to null");
- return *ptr;
- }
- operator T*() const {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr, "NonNull<T> was set to null");
- return ptr;
- }
- void operator=(T* t) {
- ptr = t;
- MOZ_ASSERT(ptr);
- #ifdef DEBUG
- inited = true;
- #endif
- }
- template<typename U>
- void operator=(U* t) {
- ptr = t->ToAStringPtr();
- MOZ_ASSERT(ptr);
- #ifdef DEBUG
- inited = true;
- #endif
- }
- T** Slot() {
- #ifdef DEBUG
- inited = true;
- #endif
- return &ptr;
- }
- T* Ptr() {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr, "NonNull<T> was set to null");
- return ptr;
- }
- // Make us work with smart-ptr helpers that expect a get()
- T* get() const {
- MOZ_ASSERT(inited);
- MOZ_ASSERT(ptr);
- return ptr;
- }
- protected:
- T* ptr;
- #ifdef DEBUG
- bool inited;
- #endif
- };
- // Class for representing sequences in arguments. We use a non-auto array
- // because that allows us to use sequences of sequences and the like. This
- // needs to be fallible because web content controls the length of the array,
- // and can easily try to create very large lengths.
- template<typename T>
- class Sequence : public FallibleTArray<T>
- {
- public:
- Sequence() : FallibleTArray<T>()
- {}
- };
- inline nsWrapperCache*
- GetWrapperCache(nsWrapperCache* cache)
- {
- return cache;
- }
- inline nsWrapperCache*
- GetWrapperCache(void* p)
- {
- return nullptr;
- }
- // Helper template for smart pointers to resolve ambiguity between
- // GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
- template <template <typename> class SmartPtr, typename T>
- inline nsWrapperCache*
- GetWrapperCache(const SmartPtr<T>& aObject)
- {
- return GetWrapperCache(aObject.get());
- }
- struct MOZ_STACK_CLASS ParentObject {
- template<class T>
- MOZ_IMPLICIT ParentObject(T* aObject) :
- mObject(aObject),
- mWrapperCache(GetWrapperCache(aObject)),
- mUseXBLScope(false)
- {}
- template<class T, template<typename> class SmartPtr>
- MOZ_IMPLICIT ParentObject(const SmartPtr<T>& aObject) :
- mObject(aObject.get()),
- mWrapperCache(GetWrapperCache(aObject.get())),
- mUseXBLScope(false)
- {}
- ParentObject(nsISupports* aObject, nsWrapperCache* aCache) :
- mObject(aObject),
- mWrapperCache(aCache),
- mUseXBLScope(false)
- {}
- // We don't want to make this an nsCOMPtr because of performance reasons, but
- // it's safe because ParentObject is a stack class.
- nsISupports* const MOZ_NON_OWNING_REF mObject;
- nsWrapperCache* const mWrapperCache;
- bool mUseXBLScope;
- };
- namespace binding_detail {
- // Class for simple sequence arguments, only used internally by codegen.
- template<typename T>
- class AutoSequence : public AutoTArray<T, 16>
- {
- public:
- AutoSequence() : AutoTArray<T, 16>()
- {}
- // Allow converting to const sequences as needed
- operator const Sequence<T>&() const {
- return *reinterpret_cast<const Sequence<T>*>(this);
- }
- };
- } // namespace binding_detail
- // Enum to represent a system or non-system caller type.
- enum class CallerType : uint32_t {
- System,
- NonSystem
- };
- } // namespace dom
- } // namespace mozilla
- #endif // mozilla_dom_BindingDeclarations_h__
|