1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/bindings/BindingDeclarations.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,489 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 1.5 +/* vim: set ts=2 sw=2 et tw=79: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/** 1.11 + * A header for declaring various things that binding implementation headers 1.12 + * might need. The idea is to make binding implementation headers safe to 1.13 + * include anywhere without running into include hell like we do with 1.14 + * BindingUtils.h 1.15 + */ 1.16 +#ifndef mozilla_dom_BindingDeclarations_h__ 1.17 +#define mozilla_dom_BindingDeclarations_h__ 1.18 + 1.19 +#include "nsStringGlue.h" 1.20 +#include "js/Value.h" 1.21 +#include "js/RootingAPI.h" 1.22 +#include "mozilla/Maybe.h" 1.23 +#include "nsCOMPtr.h" 1.24 +#include "nsTArray.h" 1.25 +#include "nsAutoPtr.h" // for nsRefPtr member variables 1.26 +#include "mozilla/dom/DOMString.h" 1.27 +#include "mozilla/dom/OwningNonNull.h" 1.28 + 1.29 +class nsWrapperCache; 1.30 + 1.31 +namespace mozilla { 1.32 +namespace dom { 1.33 + 1.34 +// Struct that serves as a base class for all dictionaries. Particularly useful 1.35 +// so we can use IsBaseOf to detect dictionary template arguments. 1.36 +struct DictionaryBase 1.37 +{ 1.38 +protected: 1.39 + bool ParseJSON(JSContext* aCx, const nsAString& aJSON, 1.40 + JS::MutableHandle<JS::Value> aVal); 1.41 +}; 1.42 + 1.43 +// Struct that serves as a base class for all typed arrays and array buffers and 1.44 +// array buffer views. Particularly useful so we can use IsBaseOf to detect 1.45 +// typed array/buffer/view template arguments. 1.46 +struct AllTypedArraysBase { 1.47 +}; 1.48 + 1.49 +// Struct that serves as a base class for all owning unions. 1.50 +// Particularly useful so we can use IsBaseOf to detect owning union 1.51 +// template arguments. 1.52 +struct AllOwningUnionBase { 1.53 +}; 1.54 + 1.55 + 1.56 +struct EnumEntry { 1.57 + const char* value; 1.58 + size_t length; 1.59 +}; 1.60 + 1.61 +class MOZ_STACK_CLASS GlobalObject 1.62 +{ 1.63 +public: 1.64 + GlobalObject(JSContext* aCx, JSObject* aObject); 1.65 + 1.66 + JSObject* Get() const 1.67 + { 1.68 + return mGlobalJSObject; 1.69 + } 1.70 + 1.71 + nsISupports* GetAsSupports() const; 1.72 + 1.73 + // The context that this returns is not guaranteed to be in the compartment of 1.74 + // the object returned from Get(), in fact it's generally in the caller's 1.75 + // compartment. 1.76 + JSContext* GetContext() const 1.77 + { 1.78 + return mCx; 1.79 + } 1.80 + 1.81 + bool Failed() const 1.82 + { 1.83 + return !Get(); 1.84 + } 1.85 + 1.86 +protected: 1.87 + JS::Rooted<JSObject*> mGlobalJSObject; 1.88 + JSContext* mCx; 1.89 + mutable nsISupports* mGlobalObject; 1.90 + mutable nsCOMPtr<nsISupports> mGlobalObjectRef; 1.91 +}; 1.92 + 1.93 +// Class for representing optional arguments. 1.94 +template<typename T, typename InternalType> 1.95 +class Optional_base 1.96 +{ 1.97 +public: 1.98 + Optional_base() 1.99 + {} 1.100 + 1.101 + explicit Optional_base(const T& aValue) 1.102 + { 1.103 + mImpl.construct(aValue); 1.104 + } 1.105 + 1.106 + template<typename T1, typename T2> 1.107 + explicit Optional_base(const T1& aValue1, const T2& aValue2) 1.108 + { 1.109 + mImpl.construct(aValue1, aValue2); 1.110 + } 1.111 + 1.112 + bool WasPassed() const 1.113 + { 1.114 + return !mImpl.empty(); 1.115 + } 1.116 + 1.117 + // Return InternalType here so we can work with it usefully. 1.118 + InternalType& Construct() 1.119 + { 1.120 + mImpl.construct(); 1.121 + return mImpl.ref(); 1.122 + } 1.123 + 1.124 + template <class T1> 1.125 + InternalType& Construct(const T1 &t1) 1.126 + { 1.127 + mImpl.construct(t1); 1.128 + return mImpl.ref(); 1.129 + } 1.130 + 1.131 + template <class T1, class T2> 1.132 + InternalType& Construct(const T1 &t1, const T2 &t2) 1.133 + { 1.134 + mImpl.construct(t1, t2); 1.135 + return mImpl.ref(); 1.136 + } 1.137 + 1.138 + void Reset() 1.139 + { 1.140 + if (WasPassed()) { 1.141 + mImpl.destroy(); 1.142 + } 1.143 + } 1.144 + 1.145 + const T& Value() const 1.146 + { 1.147 + return mImpl.ref(); 1.148 + } 1.149 + 1.150 + // Return InternalType here so we can work with it usefully. 1.151 + InternalType& Value() 1.152 + { 1.153 + return mImpl.ref(); 1.154 + } 1.155 + 1.156 + // And an explicit way to get the InternalType even if we're const. 1.157 + const InternalType& InternalValue() const 1.158 + { 1.159 + return mImpl.ref(); 1.160 + } 1.161 + 1.162 + // If we ever decide to add conversion operators for optional arrays 1.163 + // like the ones Nullable has, we'll need to ensure that Maybe<> has 1.164 + // the boolean before the actual data. 1.165 + 1.166 +private: 1.167 + // Forbid copy-construction and assignment 1.168 + Optional_base(const Optional_base& other) MOZ_DELETE; 1.169 + const Optional_base &operator=(const Optional_base &other) MOZ_DELETE; 1.170 + 1.171 +protected: 1.172 + Maybe<InternalType> mImpl; 1.173 +}; 1.174 + 1.175 +template<typename T> 1.176 +class Optional : public Optional_base<T, T> 1.177 +{ 1.178 +public: 1.179 + Optional() : 1.180 + Optional_base<T, T>() 1.181 + {} 1.182 + 1.183 + explicit Optional(const T& aValue) : 1.184 + Optional_base<T, T>(aValue) 1.185 + {} 1.186 +}; 1.187 + 1.188 +template<typename T> 1.189 +class Optional<JS::Handle<T> > : 1.190 + public Optional_base<JS::Handle<T>, JS::Rooted<T> > 1.191 +{ 1.192 +public: 1.193 + Optional() : 1.194 + Optional_base<JS::Handle<T>, JS::Rooted<T> >() 1.195 + {} 1.196 + 1.197 + Optional(JSContext* cx) : 1.198 + Optional_base<JS::Handle<T>, JS::Rooted<T> >() 1.199 + { 1.200 + this->Construct(cx); 1.201 + } 1.202 + 1.203 + Optional(JSContext* cx, const T& aValue) : 1.204 + Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue) 1.205 + {} 1.206 + 1.207 + // Override the const Value() to return the right thing so we're not 1.208 + // returning references to temporaries. 1.209 + JS::Handle<T> Value() const 1.210 + { 1.211 + return this->mImpl.ref(); 1.212 + } 1.213 + 1.214 + // And we have to override the non-const one too, since we're 1.215 + // shadowing the one on the superclass. 1.216 + JS::Rooted<T>& Value() 1.217 + { 1.218 + return this->mImpl.ref(); 1.219 + } 1.220 +}; 1.221 + 1.222 +// A specialization of Optional for JSObject* to make sure that when someone 1.223 +// calls Construct() on it we will pre-initialized the JSObject* to nullptr so 1.224 +// it can be traced safely. 1.225 +template<> 1.226 +class Optional<JSObject*> : public Optional_base<JSObject*, JSObject*> 1.227 +{ 1.228 +public: 1.229 + Optional() : 1.230 + Optional_base<JSObject*, JSObject*>() 1.231 + {} 1.232 + 1.233 + explicit Optional(JSObject* aValue) : 1.234 + Optional_base<JSObject*, JSObject*>(aValue) 1.235 + {} 1.236 + 1.237 + // Don't allow us to have an uninitialized JSObject* 1.238 + JSObject*& Construct() 1.239 + { 1.240 + // The Android compiler sucks and thinks we're trying to construct 1.241 + // a JSObject* from an int if we don't cast here. :( 1.242 + return Optional_base<JSObject*, JSObject*>::Construct( 1.243 + static_cast<JSObject*>(nullptr)); 1.244 + } 1.245 + 1.246 + template <class T1> 1.247 + JSObject*& Construct(const T1& t1) 1.248 + { 1.249 + return Optional_base<JSObject*, JSObject*>::Construct(t1); 1.250 + } 1.251 +}; 1.252 + 1.253 +// A specialization of Optional for JS::Value to make sure no one ever uses it. 1.254 +template<> 1.255 +class Optional<JS::Value> 1.256 +{ 1.257 +private: 1.258 + Optional() MOZ_DELETE; 1.259 + 1.260 + explicit Optional(JS::Value aValue) MOZ_DELETE; 1.261 +}; 1.262 + 1.263 +// A specialization of Optional for NonNull that lets us get a T& from Value() 1.264 +template<typename U> class NonNull; 1.265 +template<typename T> 1.266 +class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> > 1.267 +{ 1.268 +public: 1.269 + // We want our Value to actually return a non-const reference, even 1.270 + // if we're const. At least for things that are normally pointer 1.271 + // types... 1.272 + T& Value() const 1.273 + { 1.274 + return *this->mImpl.ref().get(); 1.275 + } 1.276 + 1.277 + // And we have to override the non-const one too, since we're 1.278 + // shadowing the one on the superclass. 1.279 + NonNull<T>& Value() 1.280 + { 1.281 + return this->mImpl.ref(); 1.282 + } 1.283 +}; 1.284 + 1.285 +// A specialization of Optional for OwningNonNull that lets us get a 1.286 +// T& from Value() 1.287 +template<typename T> 1.288 +class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> > 1.289 +{ 1.290 +public: 1.291 + // We want our Value to actually return a non-const reference, even 1.292 + // if we're const. At least for things that are normally pointer 1.293 + // types... 1.294 + T& Value() const 1.295 + { 1.296 + return *this->mImpl.ref().get(); 1.297 + } 1.298 + 1.299 + // And we have to override the non-const one too, since we're 1.300 + // shadowing the one on the superclass. 1.301 + OwningNonNull<T>& Value() 1.302 + { 1.303 + return this->mImpl.ref(); 1.304 + } 1.305 +}; 1.306 + 1.307 +// Specialization for strings. 1.308 +// XXXbz we can't pull in FakeDependentString here, because it depends on 1.309 +// internal strings. So we just have to forward-declare it and reimplement its 1.310 +// ToAStringPtr. 1.311 + 1.312 +namespace binding_detail { 1.313 +struct FakeDependentString; 1.314 +} // namespace binding_detail 1.315 + 1.316 +template<> 1.317 +class Optional<nsAString> 1.318 +{ 1.319 +public: 1.320 + Optional() : mPassed(false) {} 1.321 + 1.322 + bool WasPassed() const 1.323 + { 1.324 + return mPassed; 1.325 + } 1.326 + 1.327 + void operator=(const nsAString* str) 1.328 + { 1.329 + MOZ_ASSERT(str); 1.330 + mStr = str; 1.331 + mPassed = true; 1.332 + } 1.333 + 1.334 + // If this code ever goes away, remove the comment pointing to it in the 1.335 + // FakeDependentString class in BindingUtils.h. 1.336 + void operator=(const binding_detail::FakeDependentString* str) 1.337 + { 1.338 + MOZ_ASSERT(str); 1.339 + mStr = reinterpret_cast<const nsDependentString*>(str); 1.340 + mPassed = true; 1.341 + } 1.342 + 1.343 + const nsAString& Value() const 1.344 + { 1.345 + MOZ_ASSERT(WasPassed()); 1.346 + return *mStr; 1.347 + } 1.348 + 1.349 +private: 1.350 + // Forbid copy-construction and assignment 1.351 + Optional(const Optional& other) MOZ_DELETE; 1.352 + const Optional &operator=(const Optional &other) MOZ_DELETE; 1.353 + 1.354 + bool mPassed; 1.355 + const nsAString* mStr; 1.356 +}; 1.357 + 1.358 +template<class T> 1.359 +class NonNull 1.360 +{ 1.361 +public: 1.362 + NonNull() 1.363 +#ifdef DEBUG 1.364 + : inited(false) 1.365 +#endif 1.366 + {} 1.367 + 1.368 + operator T&() { 1.369 + MOZ_ASSERT(inited); 1.370 + MOZ_ASSERT(ptr, "NonNull<T> was set to null"); 1.371 + return *ptr; 1.372 + } 1.373 + 1.374 + operator const T&() const { 1.375 + MOZ_ASSERT(inited); 1.376 + MOZ_ASSERT(ptr, "NonNull<T> was set to null"); 1.377 + return *ptr; 1.378 + } 1.379 + 1.380 + operator T*() { 1.381 + MOZ_ASSERT(inited); 1.382 + MOZ_ASSERT(ptr, "NonNull<T> was set to null"); 1.383 + return ptr; 1.384 + } 1.385 + 1.386 + void operator=(T* t) { 1.387 + ptr = t; 1.388 + MOZ_ASSERT(ptr); 1.389 +#ifdef DEBUG 1.390 + inited = true; 1.391 +#endif 1.392 + } 1.393 + 1.394 + template<typename U> 1.395 + void operator=(U* t) { 1.396 + ptr = t->ToAStringPtr(); 1.397 + MOZ_ASSERT(ptr); 1.398 +#ifdef DEBUG 1.399 + inited = true; 1.400 +#endif 1.401 + } 1.402 + 1.403 + T** Slot() { 1.404 +#ifdef DEBUG 1.405 + inited = true; 1.406 +#endif 1.407 + return &ptr; 1.408 + } 1.409 + 1.410 + T* Ptr() { 1.411 + MOZ_ASSERT(inited); 1.412 + MOZ_ASSERT(ptr, "NonNull<T> was set to null"); 1.413 + return ptr; 1.414 + } 1.415 + 1.416 + // Make us work with smart-ptr helpers that expect a get() 1.417 + T* get() const { 1.418 + MOZ_ASSERT(inited); 1.419 + MOZ_ASSERT(ptr); 1.420 + return ptr; 1.421 + } 1.422 + 1.423 +protected: 1.424 + T* ptr; 1.425 +#ifdef DEBUG 1.426 + bool inited; 1.427 +#endif 1.428 +}; 1.429 + 1.430 +// Class for representing sequences in arguments. We use a non-auto array 1.431 +// because that allows us to use sequences of sequences and the like. This 1.432 +// needs to be fallible because web content controls the length of the array, 1.433 +// and can easily try to create very large lengths. 1.434 +template<typename T> 1.435 +class Sequence : public FallibleTArray<T> 1.436 +{ 1.437 +public: 1.438 + Sequence() : FallibleTArray<T>() 1.439 + {} 1.440 +}; 1.441 + 1.442 +inline nsWrapperCache* 1.443 +GetWrapperCache(nsWrapperCache* cache) 1.444 +{ 1.445 + return cache; 1.446 +} 1.447 + 1.448 +inline nsWrapperCache* 1.449 +GetWrapperCache(void* p) 1.450 +{ 1.451 + return nullptr; 1.452 +} 1.453 + 1.454 +// Helper template for smart pointers to resolve ambiguity between 1.455 +// GetWrappeCache(void*) and GetWrapperCache(const ParentObject&). 1.456 +template <template <typename> class SmartPtr, typename T> 1.457 +inline nsWrapperCache* 1.458 +GetWrapperCache(const SmartPtr<T>& aObject) 1.459 +{ 1.460 + return GetWrapperCache(aObject.get()); 1.461 +} 1.462 + 1.463 +struct ParentObject { 1.464 + template<class T> 1.465 + ParentObject(T* aObject) : 1.466 + mObject(aObject), 1.467 + mWrapperCache(GetWrapperCache(aObject)), 1.468 + mUseXBLScope(false) 1.469 + {} 1.470 + 1.471 + template<class T, template<typename> class SmartPtr> 1.472 + ParentObject(const SmartPtr<T>& aObject) : 1.473 + mObject(aObject.get()), 1.474 + mWrapperCache(GetWrapperCache(aObject.get())), 1.475 + mUseXBLScope(false) 1.476 + {} 1.477 + 1.478 + ParentObject(nsISupports* aObject, nsWrapperCache* aCache) : 1.479 + mObject(aObject), 1.480 + mWrapperCache(aCache), 1.481 + mUseXBLScope(false) 1.482 + {} 1.483 + 1.484 + nsISupports* const mObject; 1.485 + nsWrapperCache* const mWrapperCache; 1.486 + bool mUseXBLScope; 1.487 +}; 1.488 + 1.489 +} // namespace dom 1.490 +} // namespace mozilla 1.491 + 1.492 +#endif // mozilla_dom_BindingDeclarations_h__