dom/bindings/BindingDeclarations.h

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

mercurial