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/. */
7 #ifndef mozilla_dom_BindingUtils_h__
8 #define mozilla_dom_BindingUtils_h__
10 #include "jsfriendapi.h"
11 #include "jswrapper.h"
12 #include "mozilla/Alignment.h"
13 #include "mozilla/Array.h"
14 #include "mozilla/dom/BindingDeclarations.h"
15 #include "mozilla/dom/CallbackObject.h"
16 #include "mozilla/dom/DOMJSClass.h"
17 #include "mozilla/dom/DOMJSProxyHandler.h"
18 #include "mozilla/dom/Exceptions.h"
19 #include "mozilla/dom/NonRefcountedDOMObject.h"
20 #include "mozilla/dom/Nullable.h"
21 #include "mozilla/dom/RootedDictionary.h"
22 #include "mozilla/dom/workers/Workers.h"
23 #include "mozilla/ErrorResult.h"
24 #include "mozilla/HoldDropJSObjects.h"
25 #include "mozilla/Likely.h"
26 #include "mozilla/Util.h"
27 #include "nsCycleCollector.h"
28 #include "nsIXPConnect.h"
29 #include "MainThreadUtils.h"
30 #include "nsTraceRefcnt.h"
31 #include "qsObjectHelper.h"
32 #include "xpcpublic.h"
33 #include "nsIVariant.h"
35 #include "nsWrapperCacheInlines.h"
40 xpc_qsUnwrapArgImpl(JSContext
* cx
, JS::Handle
<JS::Value
> v
, const nsIID
& iid
, void** ppArg
,
41 nsISupports
** ppArgRef
, JS::MutableHandle
<JS::Value
> vp
);
48 SelfRef() : ptr(nullptr) {}
49 explicit SelfRef(nsISupports
*p
) : ptr(p
) {}
50 ~SelfRef() { NS_IF_RELEASE(ptr
); }
55 /** Convert a jsval to an XPCOM pointer. */
56 template <class Interface
, class StrongRefType
>
58 UnwrapArg(JSContext
* cx
, JS::Handle
<JS::Value
> v
, Interface
** ppArg
,
59 StrongRefType
** ppArgRef
, JS::MutableHandle
<JS::Value
> vp
)
61 nsISupports
* argRef
= *ppArgRef
;
62 nsresult rv
= xpc_qsUnwrapArgImpl(cx
, v
, NS_GET_TEMPLATE_IID(Interface
),
63 reinterpret_cast<void**>(ppArg
), &argRef
,
65 *ppArgRef
= static_cast<StrongRefType
*>(argRef
);
70 GetInvalidThisErrorForMethod(bool aSecurityError
)
72 return aSecurityError
? MSG_METHOD_THIS_UNWRAPPING_DENIED
:
73 MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE
;
77 GetInvalidThisErrorForGetter(bool aSecurityError
)
79 return aSecurityError
? MSG_GETTER_THIS_UNWRAPPING_DENIED
:
80 MSG_GETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE
;
84 GetInvalidThisErrorForSetter(bool aSecurityError
)
86 return aSecurityError
? MSG_SETTER_THIS_UNWRAPPING_DENIED
:
87 MSG_SETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE
;
91 ThrowInvalidThis(JSContext
* aCx
, const JS::CallArgs
& aArgs
,
92 const ErrNum aErrorNumber
,
93 const char* aInterfaceName
);
96 ThrowMethodFailedWithDetails(JSContext
* cx
, ErrorResult
& rv
,
97 const char* ifaceName
,
98 const char* memberName
,
99 bool reportJSContentExceptions
= false)
101 if (rv
.IsTypeError()) {
102 rv
.ReportTypeError(cx
);
105 if (rv
.IsJSException()) {
106 if (reportJSContentExceptions
) {
107 rv
.ReportJSExceptionFromJSImplementation(cx
);
109 rv
.ReportJSException(cx
);
113 if (rv
.IsNotEnoughArgsError()) {
114 rv
.ReportNotEnoughArgsError(cx
, ifaceName
, memberName
);
116 return Throw(cx
, rv
.ErrorCode());
119 // Returns true if the JSClass is used for DOM objects.
121 IsDOMClass(const JSClass
* clasp
)
123 return clasp
->flags
& JSCLASS_IS_DOMJSCLASS
;
127 IsDOMClass(const js::Class
* clasp
)
129 return IsDOMClass(Jsvalify(clasp
));
132 // Returns true if the JSClass is used for DOM interface and interface
133 // prototype objects.
135 IsDOMIfaceAndProtoClass(const JSClass
* clasp
)
137 return clasp
->flags
& JSCLASS_IS_DOMIFACEANDPROTOJSCLASS
;
141 IsDOMIfaceAndProtoClass(const js::Class
* clasp
)
143 return IsDOMIfaceAndProtoClass(Jsvalify(clasp
));
146 static_assert(DOM_OBJECT_SLOT
== js::PROXY_PRIVATE_SLOT
,
147 "js::PROXY_PRIVATE_SLOT doesn't match DOM_OBJECT_SLOT. "
148 "Expect bad things");
151 UnwrapDOMObject(JSObject
* obj
)
153 MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj
)) || IsDOMProxy(obj
),
154 "Don't pass non-DOM objects to this function");
156 JS::Value val
= js::GetReservedSlot(obj
, DOM_OBJECT_SLOT
);
157 return static_cast<T
*>(val
.toPrivate());
160 inline const DOMClass
*
161 GetDOMClass(JSObject
* obj
)
163 const js::Class
* clasp
= js::GetObjectClass(obj
);
164 if (IsDOMClass(clasp
)) {
165 return &DOMJSClass::FromJSClass(clasp
)->mClass
;
168 if (js::IsProxyClass(clasp
)) {
169 js::BaseProxyHandler
* handler
= js::GetProxyHandler(obj
);
170 if (handler
->family() == ProxyFamily()) {
171 return &static_cast<DOMProxyHandler
*>(handler
)->mClass
;
179 UnwrapDOMObjectToISupports(JSObject
* aObject
)
181 const DOMClass
* clasp
= GetDOMClass(aObject
);
182 if (!clasp
|| !clasp
->mDOMObjectIsISupports
) {
186 return UnwrapDOMObject
<nsISupports
>(aObject
);
190 IsDOMObject(JSObject
* obj
)
192 const js::Class
* clasp
= js::GetObjectClass(obj
);
193 return IsDOMClass(clasp
) || IsDOMProxy(obj
, clasp
);
196 #define UNWRAP_OBJECT(Interface, cx, obj, value) \
197 mozilla::dom::UnwrapObject<mozilla::dom::prototypes::id::Interface, \
198 mozilla::dom::Interface##Binding::NativeType>(cx, obj, value)
200 // Some callers don't want to set an exception when unwrapping fails
201 // (for example, overload resolution uses unwrapping to tell what sort
202 // of thing it's looking at).
203 // U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
204 template <prototypes::ID PrototypeID
, class T
, typename U
>
205 MOZ_ALWAYS_INLINE nsresult
206 UnwrapObject(JSContext
* cx
, JSObject
* obj
, U
& value
)
208 /* First check to see whether we have a DOM object */
209 const DOMClass
* domClass
= GetDOMClass(obj
);
211 /* Maybe we have a security wrapper or outer window? */
212 if (!js::IsWrapper(obj
)) {
213 /* Not a DOM object, not a wrapper, just bail */
214 return NS_ERROR_XPC_BAD_CONVERT_JS
;
217 obj
= js::CheckedUnwrap(obj
, /* stopAtOuter = */ false);
219 return NS_ERROR_XPC_SECURITY_MANAGER_VETO
;
221 MOZ_ASSERT(!js::IsWrapper(obj
));
222 domClass
= GetDOMClass(obj
);
224 /* We don't have a DOM object */
225 return NS_ERROR_XPC_BAD_CONVERT_JS
;
229 /* This object is a DOM object. Double-check that it is safely
230 castable to T by checking whether it claims to inherit from the
231 class identified by protoID. */
232 if (domClass
->mInterfaceChain
[PrototypeTraits
<PrototypeID
>::Depth
] ==
234 value
= UnwrapDOMObject
<T
>(obj
);
238 /* It's the wrong sort of DOM object */
239 return NS_ERROR_XPC_BAD_CONVERT_JS
;
243 IsNotDateOrRegExp(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
246 return !JS_ObjectIsDate(cx
, obj
) && !JS_ObjectIsRegExp(cx
, obj
);
249 MOZ_ALWAYS_INLINE
bool
250 IsArrayLike(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
252 return IsNotDateOrRegExp(cx
, obj
);
255 MOZ_ALWAYS_INLINE
bool
256 IsObjectValueConvertibleToDictionary(JSContext
* cx
,
257 JS::Handle
<JS::Value
> objVal
)
259 JS::Rooted
<JSObject
*> obj(cx
, &objVal
.toObject());
260 return IsNotDateOrRegExp(cx
, obj
);
263 MOZ_ALWAYS_INLINE
bool
264 IsConvertibleToDictionary(JSContext
* cx
, JS::Handle
<JS::Value
> val
)
266 return val
.isNullOrUndefined() ||
267 (val
.isObject() && IsObjectValueConvertibleToDictionary(cx
, val
));
270 MOZ_ALWAYS_INLINE
bool
271 IsConvertibleToCallbackInterface(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
273 return IsNotDateOrRegExp(cx
, obj
);
276 // The items in the protoAndIfaceArray are indexed by the prototypes::id::ID and
277 // constructors::id::ID enums, in that order. The end of the prototype objects
278 // should be the start of the interface objects.
279 static_assert((size_t)constructors::id::_ID_Start
==
280 (size_t)prototypes::id::_ID_Count
,
281 "Overlapping or discontiguous indexes.");
282 const size_t kProtoAndIfaceCacheCount
= constructors::id::_ID_Count
;
284 class ProtoAndIfaceArray
: public Array
<JS::Heap
<JSObject
*>, kProtoAndIfaceCacheCount
>
287 ProtoAndIfaceArray() {
288 MOZ_COUNT_CTOR(ProtoAndIfaceArray
);
291 ~ProtoAndIfaceArray() {
292 MOZ_COUNT_DTOR(ProtoAndIfaceArray
);
297 AllocateProtoAndIfaceCache(JSObject
* obj
)
299 MOZ_ASSERT(js::GetObjectClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
);
300 MOZ_ASSERT(js::GetReservedSlot(obj
, DOM_PROTOTYPE_SLOT
).isUndefined());
302 ProtoAndIfaceArray
* protoAndIfaceArray
= new ProtoAndIfaceArray();
304 js::SetReservedSlot(obj
, DOM_PROTOTYPE_SLOT
,
305 JS::PrivateValue(protoAndIfaceArray
));
309 TraceProtoAndIfaceCache(JSTracer
* trc
, JSObject
* obj
)
311 MOZ_ASSERT(js::GetObjectClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
);
313 if (!HasProtoAndIfaceArray(obj
))
315 ProtoAndIfaceArray
& protoAndIfaceArray
= *GetProtoAndIfaceArray(obj
);
316 for (size_t i
= 0; i
< ArrayLength(protoAndIfaceArray
); ++i
) {
317 if (protoAndIfaceArray
[i
]) {
318 JS_CallHeapObjectTracer(trc
, &protoAndIfaceArray
[i
], "protoAndIfaceArray[i]");
324 DestroyProtoAndIfaceCache(JSObject
* obj
)
326 MOZ_ASSERT(js::GetObjectClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
);
328 ProtoAndIfaceArray
* protoAndIfaceArray
= GetProtoAndIfaceArray(obj
);
330 delete protoAndIfaceArray
;
334 * Add constants to an object.
337 DefineConstants(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
338 const ConstantSpec
* cs
);
340 struct JSNativeHolder
343 const NativePropertyHooks
* mPropertyHooks
;
346 struct NamedConstructor
349 const JSNativeHolder mHolder
;
354 * Create a DOM interface object (if constructorClass is non-null) and/or a
355 * DOM interface prototype object (if protoClass is non-null).
357 * global is used as the parent of the interface object and the interface
359 * protoProto is the prototype to use for the interface prototype object.
360 * interfaceProto is the prototype to use for the interface object.
361 * protoClass is the JSClass to use for the interface prototype object.
362 * This is null if we should not create an interface prototype
364 * protoCache a pointer to a JSObject pointer where we should cache the
365 * interface prototype object. This must be null if protoClass is and
367 * constructorClass is the JSClass to use for the interface object.
368 * This is null if we should not create an interface object or
369 * if it should be a function object.
370 * constructor holds the JSNative to back the interface object which should be a
371 * Function, unless constructorClass is non-null in which case it is
372 * ignored. If this is null and constructorClass is also null then
373 * we should not create an interface object at all.
374 * ctorNargs is the length of the constructor function; 0 if no constructor
375 * constructorCache a pointer to a JSObject pointer where we should cache the
376 * interface object. This must be null if both constructorClass
377 * and constructor are null, and non-null otherwise.
378 * domClass is the DOMClass of instance objects for this class. This can be
379 * null if this is not a concrete proto.
380 * properties contains the methods, attributes and constants to be defined on
381 * objects in any compartment.
382 * chromeProperties contains the methods, attributes and constants to be defined
383 * on objects in chrome compartments. This must be null if the
384 * interface doesn't have any ChromeOnly properties or if the
385 * object is being created in non-chrome compartment.
386 * defineOnGlobal controls whether properties should be defined on the given
387 * global for the interface object (if any) and named
388 * constructors (if any) for this interface. This can be
389 * false in situations where we want the properties to only
390 * appear on privileged Xrays but not on the unprivileged
393 * At least one of protoClass, constructorClass or constructor should be
394 * non-null. If constructorClass or constructor are non-null, the resulting
395 * interface object will be defined on the given global with property name
396 * |name|, which must also be non-null.
399 CreateInterfaceObjects(JSContext
* cx
, JS::Handle
<JSObject
*> global
,
400 JS::Handle
<JSObject
*> protoProto
,
401 const JSClass
* protoClass
, JS::Heap
<JSObject
*>* protoCache
,
402 JS::Handle
<JSObject
*> interfaceProto
,
403 const JSClass
* constructorClass
, const JSNativeHolder
* constructor
,
404 unsigned ctorNargs
, const NamedConstructor
* namedConstructors
,
405 JS::Heap
<JSObject
*>* constructorCache
, const DOMClass
* domClass
,
406 const NativeProperties
* regularProperties
,
407 const NativeProperties
* chromeOnlyProperties
,
408 const char* name
, bool defineOnGlobal
);
411 * Define the unforgeable attributes on an object.
414 DefineUnforgeableAttributes(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
415 const Prefable
<const JSPropertySpec
>* props
);
418 DefineWebIDLBindingPropertiesOnXPCObject(JSContext
* cx
,
419 JS::Handle
<JSObject
*> obj
,
420 const NativeProperties
* properties
,
421 bool defineUnforgeableAttributes
);
424 #define HAS_MEMBER_CHECK(_name) \
425 template<typename V> static yes& Check(char (*)[(&V::_name == 0) + 1])
427 #define HAS_MEMBER_CHECK(_name) \
428 template<typename V> static yes& Check(char (*)[sizeof(&V::_name) + 1])
431 #define HAS_MEMBER(_name) \
432 template<typename T> \
433 class Has##_name##Member { \
434 typedef char yes[1]; \
435 typedef char no[2]; \
436 HAS_MEMBER_CHECK(_name); \
437 template<typename V> static no& Check(...); \
440 static bool const Value = sizeof(Check<T>(nullptr)) == sizeof(yes); \
443 HAS_MEMBER(WrapObject
)
445 // HasWrapObject<T>::Value will be true if T has a WrapObject member but it's
446 // not nsWrapperCache::WrapObject.
453 typedef JSObject
* (nsWrapperCache::*WrapObject
)(JSContext
*,
454 JS::Handle
<JSObject
*>);
455 template<typename U
, U
> struct SFINAE
;
456 template <typename V
> static no
& Check(SFINAE
<WrapObject
, &V::WrapObject
>*);
457 template <typename V
> static yes
& Check(...);
460 static bool const Value
= HasWrapObjectMember
<T
>::Value
&&
461 sizeof(Check
<T
>(nullptr)) == sizeof(yes
);
465 template <class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
467 CheckWrapperCacheCast
471 return reinterpret_cast<uintptr_t>(
472 static_cast<nsWrapperCache
*>(
473 reinterpret_cast<T
*>(1))) == 1;
478 CheckWrapperCacheCast
<T
, true>
487 MOZ_ALWAYS_INLINE
bool
488 CouldBeDOMBinding(void*)
493 MOZ_ALWAYS_INLINE
bool
494 CouldBeDOMBinding(nsWrapperCache
* aCache
)
496 return aCache
->IsDOMBinding();
499 // The DOM_OBJECT_SLOT_SOW slot contains a JS::ObjectValue which points to the
500 // cached system object wrapper (SOW) or JS::UndefinedValue if this class
501 // doesn't need SOWs.
503 inline const JS::Value
&
504 GetSystemOnlyWrapperSlot(JSObject
* obj
)
506 MOZ_ASSERT(IsDOMClass(js::GetObjectJSClass(obj
)) &&
507 !(js::GetObjectJSClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
));
508 return js::GetReservedSlot(obj
, DOM_OBJECT_SLOT_SOW
);
511 SetSystemOnlyWrapperSlot(JSObject
* obj
, const JS::Value
& v
)
513 MOZ_ASSERT(IsDOMClass(js::GetObjectJSClass(obj
)) &&
514 !(js::GetObjectJSClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
));
515 js::SetReservedSlot(obj
, DOM_OBJECT_SLOT_SOW
, v
);
519 GetSameCompartmentWrapperForDOMBinding(JSObject
*& obj
)
521 const js::Class
* clasp
= js::GetObjectClass(obj
);
522 if (dom::IsDOMClass(clasp
)) {
523 if (!(clasp
->flags
& JSCLASS_DOM_GLOBAL
)) {
524 JS::Value v
= GetSystemOnlyWrapperSlot(obj
);
531 return IsDOMProxy(obj
, clasp
);
535 SetSystemOnlyWrapper(JSObject
* obj
, nsWrapperCache
* cache
, JSObject
& wrapper
)
537 SetSystemOnlyWrapperSlot(obj
, JS::ObjectValue(wrapper
));
538 cache
->SetHasSystemOnlyWrapper();
541 // Make sure to wrap the given string value into the right compartment, as
545 MaybeWrapStringValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
547 MOZ_ASSERT(rval
.isString());
548 JSString
* str
= rval
.toString();
549 if (JS::GetGCThingZone(str
) != js::GetContextZone(cx
)) {
550 return JS_WrapValue(cx
, rval
);
555 // Make sure to wrap the given object value into the right compartment as
556 // needed. This will work correctly, but possibly slowly, on all objects.
559 MaybeWrapObjectValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
561 MOZ_ASSERT(rval
.isObject());
563 JSObject
* obj
= &rval
.toObject();
564 if (js::GetObjectCompartment(obj
) != js::GetContextCompartment(cx
)) {
565 return JS_WrapValue(cx
, rval
);
568 // We're same-compartment, but even then we might need to wrap
569 // objects specially. Check for that.
570 if (GetSameCompartmentWrapperForDOMBinding(obj
)) {
571 // We're a new-binding object, and "obj" now points to the right thing
572 rval
.set(JS::ObjectValue(*obj
));
576 // It's not a WebIDL object. But it might be an XPConnect one, in which case
577 // we may need to outerize here, so make sure to call JS_WrapValue.
578 return JS_WrapValue(cx
, rval
);
581 // Like MaybeWrapObjectValue, but also allows null
584 MaybeWrapObjectOrNullValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
586 MOZ_ASSERT(rval
.isObjectOrNull());
590 return MaybeWrapObjectValue(cx
, rval
);
593 // Wrapping for objects that are known to not be DOM or XPConnect objects
596 MaybeWrapNonDOMObjectValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
598 MOZ_ASSERT(rval
.isObject());
599 MOZ_ASSERT(!GetDOMClass(&rval
.toObject()));
600 MOZ_ASSERT(!(js::GetObjectClass(&rval
.toObject())->flags
&
601 JSCLASS_PRIVATE_IS_NSISUPPORTS
));
603 JSObject
* obj
= &rval
.toObject();
604 if (js::GetObjectCompartment(obj
) == js::GetContextCompartment(cx
)) {
607 return JS_WrapValue(cx
, rval
);
610 // Like MaybeWrapNonDOMObjectValue but allows null
613 MaybeWrapNonDOMObjectOrNullValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
615 MOZ_ASSERT(rval
.isObjectOrNull());
619 return MaybeWrapNonDOMObjectValue(cx
, rval
);
622 // If rval is a gcthing and is not in the compartment of cx, wrap rval
623 // into the compartment of cx (typically by replacing it with an Xray or
624 // cross-compartment wrapper around the original object).
625 MOZ_ALWAYS_INLINE
bool
626 MaybeWrapValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
628 if (rval
.isString()) {
629 return MaybeWrapStringValue(cx
, rval
);
632 if (!rval
.isObject()) {
636 return MaybeWrapObjectValue(cx
, rval
);
640 WrapNewBindingForSameCompartment(JSContext
* cx
, JSObject
* obj
, void* value
,
641 JS::MutableHandle
<JS::Value
> rval
)
643 rval
.set(JS::ObjectValue(*obj
));
647 WrapNewBindingForSameCompartment(JSContext
* cx
, JSObject
* obj
,
648 nsWrapperCache
* value
,
649 JS::MutableHandle
<JS::Value
> rval
)
651 if (value
->HasSystemOnlyWrapper()) {
652 rval
.set(GetSystemOnlyWrapperSlot(obj
));
653 MOZ_ASSERT(rval
.isObject());
655 rval
.set(JS::ObjectValue(*obj
));
659 // Create a JSObject wrapping "value", if there isn't one already, and store it
660 // in rval. "value" must be a concrete class that implements a
661 // GetWrapperPreserveColor() which can return its existing wrapper, if any, and
662 // a WrapObject() which will try to create a wrapper. Typically, this is done by
663 // having "value" inherit from nsWrapperCache.
665 MOZ_ALWAYS_INLINE
bool
666 WrapNewBindingObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
* value
,
667 JS::MutableHandle
<JS::Value
> rval
)
670 JSObject
* obj
= value
->GetWrapperPreserveColor();
671 bool couldBeDOMBinding
= CouldBeDOMBinding(value
);
673 JS::ExposeObjectToActiveJS(obj
);
675 // Inline this here while we have non-dom objects in wrapper caches.
676 if (!couldBeDOMBinding
) {
680 obj
= value
->WrapObject(cx
, scope
);
682 // At this point, obj is null, so just return false.
683 // Callers seem to be testing JS_IsExceptionPending(cx) to
684 // figure out whether WrapObject() threw.
690 const DOMClass
* clasp
= GetDOMClass(obj
);
691 // clasp can be null if the cache contained a non-DOM object from a
692 // different compartment than scope.
694 // Some sanity asserts about our object. Specifically:
695 // 1) If our class claims we're nsISupports, we better be nsISupports
696 // XXXbz ideally, we could assert that reinterpret_cast to nsISupports
697 // does the right thing, but I don't see a way to do it. :(
698 // 2) If our class doesn't claim we're nsISupports we better be
699 // reinterpret_castable to nsWrapperCache.
700 MOZ_ASSERT(clasp
, "What happened here?");
701 MOZ_ASSERT_IF(clasp
->mDOMObjectIsISupports
, (IsBaseOf
<nsISupports
, T
>::value
));
702 MOZ_ASSERT(CheckWrapperCacheCast
<T
>::Check());
705 // When called via XrayWrapper, we end up here while running in the
706 // chrome compartment. But the obj we have would be created in
707 // whatever the content compartment is. So at this point we need to
708 // make sure it's correctly wrapped for the compartment of |scope|.
709 // cx should already be in the compartment of |scope| here.
710 MOZ_ASSERT(js::IsObjectInContextCompartment(scope
, cx
));
713 bool sameCompartment
=
714 js::GetObjectCompartment(obj
) == js::GetContextCompartment(cx
);
715 if (sameCompartment
&& couldBeDOMBinding
) {
716 WrapNewBindingForSameCompartment(cx
, obj
, value
, rval
);
720 rval
.set(JS::ObjectValue(*obj
));
721 return JS_WrapValue(cx
, rval
);
724 // Create a JSObject wrapping "value", for cases when "value" is a
725 // non-wrapper-cached object using WebIDL bindings. "value" must implement a
726 // WrapObject() method taking a JSContext and a scope.
729 WrapNewBindingNonWrapperCachedObject(JSContext
* cx
,
730 JS::Handle
<JSObject
*> scopeArg
,
732 JS::MutableHandle
<JS::Value
> rval
)
735 // We try to wrap in the compartment of the underlying object of "scope"
736 JS::Rooted
<JSObject
*> obj(cx
);
738 // scope for the JSAutoCompartment so that we restore the compartment
739 // before we call JS_WrapValue.
740 Maybe
<JSAutoCompartment
> ac
;
741 // Maybe<Handle> doesn't so much work, and in any case, adding
742 // more Maybe (one for a Rooted and one for a Handle) adds more
743 // code (and branches!) than just adding a single rooted.
744 JS::Rooted
<JSObject
*> scope(cx
, scopeArg
);
745 if (js::IsWrapper(scope
)) {
746 scope
= js::CheckedUnwrap(scope
, /* stopAtOuter = */ false);
749 ac
.construct(cx
, scope
);
752 obj
= value
->WrapObject(cx
, scope
);
759 // We can end up here in all sorts of compartments, per above. Make
760 // sure to JS_WrapValue!
761 rval
.set(JS::ObjectValue(*obj
));
762 return JS_WrapValue(cx
, rval
);
765 // Create a JSObject wrapping "value", for cases when "value" is a
766 // non-wrapper-cached owned object using WebIDL bindings. "value" must implement a
767 // WrapObject() method taking a JSContext, a scope, and a boolean outparam that
768 // is true if the JSObject took ownership
771 WrapNewBindingNonWrapperCachedOwnedObject(JSContext
* cx
,
772 JS::Handle
<JSObject
*> scopeArg
,
774 JS::MutableHandle
<JS::Value
> rval
)
776 // We do a runtime check on value, because otherwise we might in
777 // fact end up wrapping a null and invoking methods on it later.
779 NS_RUNTIMEABORT("Don't try to wrap null objects");
781 // We try to wrap in the compartment of the underlying object of "scope"
782 JS::Rooted
<JSObject
*> obj(cx
);
784 // scope for the JSAutoCompartment so that we restore the compartment
785 // before we call JS_WrapValue.
786 Maybe
<JSAutoCompartment
> ac
;
787 // Maybe<Handle> doesn't so much work, and in any case, adding
788 // more Maybe (one for a Rooted and one for a Handle) adds more
789 // code (and branches!) than just adding a single rooted.
790 JS::Rooted
<JSObject
*> scope(cx
, scopeArg
);
791 if (js::IsWrapper(scope
)) {
792 scope
= js::CheckedUnwrap(scope
, /* stopAtOuter = */ false);
795 ac
.construct(cx
, scope
);
798 bool tookOwnership
= false;
799 obj
= value
->WrapObject(cx
, scope
, &tookOwnership
);
800 MOZ_ASSERT_IF(obj
, tookOwnership
);
810 // We can end up here in all sorts of compartments, per above. Make
811 // sure to JS_WrapValue!
812 rval
.set(JS::ObjectValue(*obj
));
813 return JS_WrapValue(cx
, rval
);
816 // Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
817 template <template <typename
> class SmartPtr
, typename T
>
819 WrapNewBindingNonWrapperCachedObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
820 const SmartPtr
<T
>& value
,
821 JS::MutableHandle
<JS::Value
> rval
)
823 return WrapNewBindingNonWrapperCachedObject(cx
, scope
, value
.get(), rval
);
826 // Only set allowNativeWrapper to false if you really know you need it, if in
827 // doubt use true. Setting it to false disables security wrappers.
829 NativeInterface2JSObjectAndThrowIfFailed(JSContext
* aCx
,
830 JS::Handle
<JSObject
*> aScope
,
831 JS::MutableHandle
<JS::Value
> aRetval
,
832 xpcObjectHelper
& aHelper
,
834 bool aAllowNativeWrapper
);
837 * A method to handle new-binding wrap failure, by possibly falling back to
838 * wrapping as a non-new-binding object.
841 MOZ_ALWAYS_INLINE
bool
842 HandleNewBindingWrappingFailure(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
843 T
* value
, JS::MutableHandle
<JS::Value
> rval
)
845 if (JS_IsExceptionPending(cx
)) {
849 qsObjectHelper
helper(value
, GetWrapperCache(value
));
850 return NativeInterface2JSObjectAndThrowIfFailed(cx
, scope
, rval
,
851 helper
, nullptr, true);
854 // Helper for calling HandleNewBindingWrappingFailure with smart pointers
855 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
858 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
859 struct HandleNewBindingWrappingFailureHelper
861 static inline bool Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
862 const T
& value
, JS::MutableHandle
<JS::Value
> rval
)
864 return HandleNewBindingWrappingFailure(cx
, scope
, value
.get(), rval
);
869 struct HandleNewBindingWrappingFailureHelper
<T
, false>
871 static inline bool Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
& value
,
872 JS::MutableHandle
<JS::Value
> rval
)
874 return HandleNewBindingWrappingFailure(cx
, scope
, &value
, rval
);
880 HandleNewBindingWrappingFailure(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
881 T
& value
, JS::MutableHandle
<JS::Value
> rval
)
883 return HandleNewBindingWrappingFailureHelper
<T
>::Wrap(cx
, scope
, value
, rval
);
888 EnumValueNotFound(JSContext
* cx
, const jschar
* chars
, size_t length
,
889 const char* type
, const char* sourceDescription
)
896 EnumValueNotFound
<false>(JSContext
* cx
, const jschar
* chars
, size_t length
,
897 const char* type
, const char* sourceDescription
)
899 // TODO: Log a warning to the console.
905 EnumValueNotFound
<true>(JSContext
* cx
, const jschar
* chars
, size_t length
,
906 const char* type
, const char* sourceDescription
)
908 NS_LossyConvertUTF16toASCII
deflated(static_cast<const PRUnichar
*>(chars
),
910 return ThrowErrorMessage(cx
, MSG_INVALID_ENUM_VALUE
, sourceDescription
,
911 deflated
.get(), type
);
915 template<bool InvalidValueFatal
>
917 FindEnumStringIndex(JSContext
* cx
, JS::Handle
<JS::Value
> v
, const EnumEntry
* values
,
918 const char* type
, const char* sourceDescription
, bool* ok
)
920 // JS_StringEqualsAscii is slow as molasses, so don't use it here.
921 JSString
* str
= JS::ToString(cx
, v
);
926 JS::Anchor
<JSString
*> anchor(str
);
928 const jschar
* chars
= JS_GetStringCharsAndLength(cx
, str
, &length
);
934 for (const EnumEntry
* value
= values
; value
->value
; ++value
, ++i
) {
935 if (length
!= value
->length
) {
940 const char* val
= value
->value
;
941 for (size_t j
= 0; j
!= length
; ++j
) {
942 if (unsigned(val
[j
]) != unsigned(chars
[j
])) {
954 *ok
= EnumValueNotFound
<InvalidValueFatal
>(cx
, chars
, length
, type
,
959 inline nsWrapperCache
*
960 GetWrapperCache(const ParentObject
& aParentObject
)
962 return aParentObject
.mWrapperCache
;
967 GetParentPointer(T
* aObject
)
973 GetParentPointer(const ParentObject
& aObject
)
975 return aObject
.mObject
;
980 ClearWrapper(T
* p
, nsWrapperCache
* cache
)
982 cache
->ClearWrapper();
987 ClearWrapper(T
* p
, void*)
989 nsWrapperCache
* cache
;
990 CallQueryInterface(p
, &cache
);
991 ClearWrapper(p
, cache
);
994 // Attempt to preserve the wrapper, if any, for a Paris DOM bindings object.
995 // Return true if we successfully preserved the wrapper, or there is no wrapper
996 // to preserve. In the latter case we don't need to preserve the wrapper, because
997 // the object can only be obtained by JS once, or they cannot be meaningfully
998 // owned from the native side.
1000 // This operation will return false only for non-nsISupports cycle-collected
1001 // objects, because we cannot determine if they are wrappercached or not.
1003 TryPreserveWrapper(JSObject
* obj
);
1005 // Can only be called with the immediate prototype of the instance object. Can
1006 // only be called on the prototype of an object known to be a DOM instance.
1008 InstanceClassHasProtoAtDepth(JSObject
* protoObject
, uint32_t protoID
,
1011 // Only set allowNativeWrapper to false if you really know you need it, if in
1012 // doubt use true. Setting it to false disables security wrappers.
1014 XPCOMObjectToJsval(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1015 xpcObjectHelper
& helper
, const nsIID
* iid
,
1016 bool allowNativeWrapper
, JS::MutableHandle
<JS::Value
> rval
);
1018 // Special-cased wrapping for variants
1020 VariantToJsval(JSContext
* aCx
, JS::Handle
<JSObject
*> aScope
,
1021 nsIVariant
* aVariant
, JS::MutableHandle
<JS::Value
> aRetval
);
1023 // Wrap an object "p" which is not using WebIDL bindings yet. This _will_
1024 // actually work on WebIDL binding objects that are wrappercached, but will be
1025 // much slower than WrapNewBindingObject. "cache" must either be null or be the
1026 // nsWrapperCache for "p".
1029 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
* p
,
1030 nsWrapperCache
* cache
, const nsIID
* iid
,
1031 JS::MutableHandle
<JS::Value
> rval
)
1033 if (xpc_FastGetCachedWrapper(cache
, scope
, rval
))
1035 qsObjectHelper
helper(p
, cache
);
1036 return XPCOMObjectToJsval(cx
, scope
, helper
, iid
, true, rval
);
1039 // A specialization of the above for nsIVariant, because that needs to
1040 // do something different.
1043 WrapObject
<nsIVariant
>(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, nsIVariant
* p
,
1044 nsWrapperCache
* cache
, const nsIID
* iid
,
1045 JS::MutableHandle
<JS::Value
> rval
)
1048 MOZ_ASSERT(iid
->Equals(NS_GET_IID(nsIVariant
)));
1049 return VariantToJsval(cx
, scope
, p
, rval
);
1052 // Wrap an object "p" which is not using WebIDL bindings yet. Just like the
1053 // variant that takes an nsWrapperCache above, but will try to auto-derive the
1054 // nsWrapperCache* from "p".
1057 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
* p
, const nsIID
* iid
,
1058 JS::MutableHandle
<JS::Value
> rval
)
1060 return WrapObject(cx
, scope
, p
, GetWrapperCache(p
), iid
, rval
);
1063 // Just like the WrapObject above, but without requiring you to pick which
1064 // interface you're wrapping as. This should only be used for objects that have
1065 // classinfo, for which it doesn't matter what IID is used to wrap.
1068 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
* p
,
1069 JS::MutableHandle
<JS::Value
> rval
)
1071 return WrapObject(cx
, scope
, p
, nullptr, rval
);
1074 // Helper to make it possible to wrap directly out of an nsCOMPtr
1077 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, const nsCOMPtr
<T
>& p
,
1078 const nsIID
* iid
, JS::MutableHandle
<JS::Value
> rval
)
1080 return WrapObject(cx
, scope
, p
.get(), iid
, rval
);
1083 // Helper to make it possible to wrap directly out of an nsCOMPtr
1086 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, const nsCOMPtr
<T
>& p
,
1087 JS::MutableHandle
<JS::Value
> rval
)
1089 return WrapObject(cx
, scope
, p
, nullptr, rval
);
1092 // Helper to make it possible to wrap directly out of an nsRefPtr
1095 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, const nsRefPtr
<T
>& p
,
1096 const nsIID
* iid
, JS::MutableHandle
<JS::Value
> rval
)
1098 return WrapObject(cx
, scope
, p
.get(), iid
, rval
);
1101 // Helper to make it possible to wrap directly out of an nsRefPtr
1104 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, const nsRefPtr
<T
>& p
,
1105 JS::MutableHandle
<JS::Value
> rval
)
1107 return WrapObject(cx
, scope
, p
, nullptr, rval
);
1110 // Specialization to make it easy to use WrapObject in codegen.
1113 WrapObject
<JSObject
>(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, JSObject
* p
,
1114 JS::MutableHandle
<JS::Value
> rval
)
1116 rval
.set(JS::ObjectOrNullValue(p
));
1121 WrapObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, JSObject
& p
,
1122 JS::MutableHandle
<JS::Value
> rval
)
1124 rval
.set(JS::ObjectValue(p
));
1128 // Given an object "p" that inherits from nsISupports, wrap it and return the
1129 // result. Null is returned on wrapping failure. This is somewhat similar to
1130 // WrapObject() above, but does NOT allow Xrays around the result, since we
1131 // don't want those for our parent object.
1132 template<typename T
>
1133 static inline JSObject
*
1134 WrapNativeISupportsParent(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
* p
,
1135 nsWrapperCache
* cache
)
1137 qsObjectHelper
helper(ToSupports(p
), cache
);
1138 JS::Rooted
<JS::Value
> v(cx
);
1139 return XPCOMObjectToJsval(cx
, scope
, helper
, nullptr, false, &v
) ?
1140 v
.toObjectOrNull() :
1145 // Fallback for when our parent is not a WebIDL binding object.
1146 template<typename T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
1147 struct WrapNativeParentFallback
1149 static inline JSObject
* Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1150 T
* parent
, nsWrapperCache
* cache
)
1156 // Fallback for when our parent is not a WebIDL binding object but _is_ an
1157 // nsISupports object.
1158 template<typename T
>
1159 struct WrapNativeParentFallback
<T
, true >
1161 static inline JSObject
* Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1162 T
* parent
, nsWrapperCache
* cache
)
1164 return WrapNativeISupportsParent(cx
, scope
, parent
, cache
);
1168 // Wrapping of our native parent, for cases when it's a WebIDL object (though
1169 // possibly preffed off).
1170 template<typename T
, bool hasWrapObject
=HasWrapObject
<T
>::Value
>
1171 struct WrapNativeParentHelper
1173 static inline JSObject
* Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1174 T
* parent
, nsWrapperCache
* cache
)
1179 if ((obj
= cache
->GetWrapper())) {
1183 // Inline this here while we have non-dom objects in wrapper caches.
1184 if (!CouldBeDOMBinding(parent
)) {
1185 obj
= WrapNativeParentFallback
<T
>::Wrap(cx
, scope
, parent
, cache
);
1187 obj
= parent
->WrapObject(cx
, scope
);
1194 // Wrapping of our native parent, for cases when it's not a WebIDL object. In
1195 // this case it must be nsISupports.
1196 template<typename T
>
1197 struct WrapNativeParentHelper
<T
, false >
1199 static inline JSObject
* Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1200 T
* parent
, nsWrapperCache
* cache
)
1203 if (cache
&& (obj
= cache
->GetWrapper())) {
1205 NS_ASSERTION(WrapNativeISupportsParent(cx
, scope
, parent
, cache
) == obj
,
1206 "Unexpected object in nsWrapperCache");
1211 return WrapNativeISupportsParent(cx
, scope
, parent
, cache
);
1215 // Wrapping of our native parent.
1216 template<typename T
>
1217 static inline JSObject
*
1218 WrapNativeParent(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
* p
,
1219 nsWrapperCache
* cache
)
1225 return WrapNativeParentHelper
<T
>::Wrap(cx
, scope
, p
, cache
);
1228 // Wrapping of our native parent, when we don't want to explicitly pass in
1229 // things like the nsWrapperCache for it.
1230 template<typename T
>
1231 static inline JSObject
*
1232 WrapNativeParent(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, const T
& p
)
1234 return WrapNativeParent(cx
, scope
, GetParentPointer(p
), GetWrapperCache(p
));
1237 // A way to differentiate between nodes, which use the parent object
1238 // returned by native->GetParentObject(), and all other objects, which
1239 // just use the parent's global.
1240 static inline JSObject
*
1241 GetRealParentObject(void* aParent
, JSObject
* aParentObject
)
1243 return aParentObject
?
1244 js::GetGlobalForObjectCrossCompartment(aParentObject
) : nullptr;
1247 static inline JSObject
*
1248 GetRealParentObject(Element
* aParent
, JSObject
* aParentObject
)
1250 return aParentObject
;
1253 HAS_MEMBER(GetParentObject
)
1255 template<typename T
, bool WrapperCached
=HasGetParentObjectMember
<T
>::Value
>
1256 struct GetParentObject
1258 static JSObject
* Get(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
1260 T
* native
= UnwrapDOMObject
<T
>(obj
);
1262 GetRealParentObject(native
,
1263 WrapNativeParent(cx
, obj
, native
->GetParentObject()));
1267 template<typename T
>
1268 struct GetParentObject
<T
, false>
1270 static JSObject
* Get(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
1278 JSObject
* GetJSObjectFromCallback(CallbackObject
* callback
)
1280 return callback
->Callback();
1284 JSObject
* GetJSObjectFromCallback(void* noncallback
)
1289 template<typename T
>
1290 static inline JSObject
*
1291 WrapCallThisObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, const T
& p
)
1293 // Callbacks are nsISupports, so WrapNativeParent will just happily wrap them
1294 // up as an nsISupports XPCWrappedNative... which is not at all what we want.
1295 // So we need to special-case them.
1296 JS::Rooted
<JSObject
*> obj(cx
, GetJSObjectFromCallback(p
));
1298 // WrapNativeParent is a bit of a Swiss army knife that will
1299 // wrap anything for us.
1300 obj
= WrapNativeParent(cx
, scope
, p
);
1306 // But all that won't necessarily put things in the compartment of cx.
1307 if (!JS_WrapObject(cx
, &obj
)) {
1314 // Helper for calling WrapNewBindingObject with smart pointers
1315 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
1316 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
1317 struct WrapNewBindingObjectHelper
1319 static inline bool Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1320 const T
& value
, JS::MutableHandle
<JS::Value
> rval
)
1322 return WrapNewBindingObject(cx
, scope
, value
.get(), rval
);
1327 struct WrapNewBindingObjectHelper
<T
, false>
1329 static inline bool Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
& value
,
1330 JS::MutableHandle
<JS::Value
> rval
)
1332 return WrapNewBindingObject(cx
, scope
, &value
, rval
);
1338 WrapNewBindingObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
& value
,
1339 JS::MutableHandle
<JS::Value
> rval
)
1341 return WrapNewBindingObjectHelper
<T
>::Wrap(cx
, scope
, value
, rval
);
1346 GetCallbackFromCallbackObject(T
* aObj
)
1348 return aObj
->Callback();
1351 // Helper for getting the callback JSObject* of a smart ptr around a
1352 // CallbackObject or a reference to a CallbackObject or something like
1354 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
1355 struct GetCallbackFromCallbackObjectHelper
1357 static inline JSObject
* Get(const T
& aObj
)
1359 return GetCallbackFromCallbackObject(aObj
.get());
1364 struct GetCallbackFromCallbackObjectHelper
<T
, false>
1366 static inline JSObject
* Get(T
& aObj
)
1368 return GetCallbackFromCallbackObject(&aObj
);
1374 GetCallbackFromCallbackObject(T
& aObj
)
1376 return GetCallbackFromCallbackObjectHelper
<T
>::Get(aObj
);
1380 InternJSString(JSContext
* cx
, jsid
& id
, const char* chars
)
1382 if (JSString
*str
= ::JS_InternString(cx
, chars
)) {
1383 id
= INTERNED_STRING_TO_JSID(cx
, str
);
1389 // Spec needs a name property
1390 template <typename Spec
>
1392 InitIds(JSContext
* cx
, const Prefable
<Spec
>* prefableSpecs
, jsid
* ids
)
1394 MOZ_ASSERT(prefableSpecs
);
1395 MOZ_ASSERT(prefableSpecs
->specs
);
1397 // We ignore whether the set of ids is enabled and just intern all the IDs,
1398 // because this is only done once per application runtime.
1399 Spec
* spec
= prefableSpecs
->specs
;
1401 if (!InternJSString(cx
, *ids
, spec
->name
)) {
1404 } while (++ids
, (++spec
)->name
);
1406 // We ran out of ids for that pref. Put a JSID_VOID in on the id
1407 // corresponding to the list terminator for the pref.
1410 } while ((++prefableSpecs
)->specs
);
1416 QueryInterface(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
1422 static_assert(IsBaseOf
<nsISupports
, T
>::value
,
1423 "QueryInterface can't work without an nsISupports.");
1424 static bool Enabled(JSContext
* aCx
, JSObject
* aGlobal
)
1426 return NS_IsMainThread() && IsChromeOrXBL(aCx
, aGlobal
);
1431 ThrowingConstructor(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
1433 // vp is allowed to be null; in that case no get will be attempted,
1434 // and *found will simply indicate whether the property exists.
1436 GetPropertyOnPrototype(JSContext
* cx
, JS::Handle
<JSObject
*> proxy
,
1437 JS::Handle
<jsid
> id
, bool* found
,
1441 HasPropertyOnPrototype(JSContext
* cx
, JS::Handle
<JSObject
*> proxy
,
1442 JS::Handle
<jsid
> id
);
1445 // Append the property names in "names" to "props". If
1446 // shadowPrototypeProperties is false then skip properties that are also
1447 // present on the proto chain of proxy. If shadowPrototypeProperties is true,
1448 // then the "proxy" argument is ignored.
1450 AppendNamedPropertyIds(JSContext
* cx
, JS::Handle
<JSObject
*> proxy
,
1451 nsTArray
<nsString
>& names
,
1452 bool shadowPrototypeProperties
, JS::AutoIdVector
& props
);
1454 // A struct that has the same layout as an nsDependentString but much
1455 // faster constructor and destructor behavior
1456 struct FakeDependentString
{
1457 FakeDependentString() :
1458 mFlags(nsDependentString::F_TERMINATED
)
1462 void SetData(const nsDependentString::char_type
* aData
,
1463 nsDependentString::size_type aLength
) {
1464 MOZ_ASSERT(mFlags
== nsDependentString::F_TERMINATED
);
1470 mData
= nsDependentString::char_traits::sEmptyBuffer
;
1476 mFlags
|= nsDependentString::F_VOIDED
;
1479 const nsDependentString::char_type
* Data() const
1484 nsDependentString::size_type
Length() const
1489 // If this ever changes, change the corresponding code in the
1490 // Optional<nsAString> specialization as well.
1491 const nsAString
* ToAStringPtr() const {
1492 return reinterpret_cast<const nsDependentString
*>(this);
1495 nsAString
* ToAStringPtr() {
1496 return reinterpret_cast<nsDependentString
*>(this);
1499 operator const nsAString
& () const {
1500 return *reinterpret_cast<const nsDependentString
*>(this);
1504 const nsDependentString::char_type
* mData
;
1505 nsDependentString::size_type mLength
;
1508 // A class to use for our static asserts to ensure our object layout
1509 // matches that of nsDependentString.
1510 class DependentStringAsserter
;
1511 friend class DependentStringAsserter
;
1513 class DepedentStringAsserter
: public nsDependentString
{
1515 static void StaticAsserts() {
1516 static_assert(sizeof(FakeDependentString
) == sizeof(nsDependentString
),
1517 "Must have right object size");
1518 static_assert(offsetof(FakeDependentString
, mData
) ==
1519 offsetof(DepedentStringAsserter
, mData
),
1520 "Offset of mData should match");
1521 static_assert(offsetof(FakeDependentString
, mLength
) ==
1522 offsetof(DepedentStringAsserter
, mLength
),
1523 "Offset of mLength should match");
1524 static_assert(offsetof(FakeDependentString
, mFlags
) ==
1525 offsetof(DepedentStringAsserter
, mFlags
),
1526 "Offset of mFlags should match");
1531 enum StringificationBehavior
{
1537 // pval must not be null and must point to a rooted JS::Value
1539 ConvertJSValueToString(JSContext
* cx
, JS::Handle
<JS::Value
> v
,
1540 JS::MutableHandle
<JS::Value
> pval
,
1541 StringificationBehavior nullBehavior
,
1542 StringificationBehavior undefinedBehavior
,
1543 FakeDependentString
& result
)
1549 StringificationBehavior behavior
;
1551 behavior
= nullBehavior
;
1552 } else if (v
.isUndefined()) {
1553 behavior
= undefinedBehavior
;
1555 behavior
= eStringify
;
1558 if (behavior
!= eStringify
) {
1559 if (behavior
== eEmpty
) {
1567 s
= JS::ToString(cx
, v
);
1571 pval
.set(JS::StringValue(s
)); // Root the new string.
1575 const jschar
*chars
= JS_GetStringCharsZAndLength(cx
, s
, &len
);
1580 result
.SetData(chars
, len
);
1585 ConvertJSValueToByteString(JSContext
* cx
, JS::Handle
<JS::Value
> v
,
1586 JS::MutableHandle
<JS::Value
> pval
, bool nullable
,
1587 nsACString
& result
);
1589 template<typename T
>
1590 void DoTraceSequence(JSTracer
* trc
, FallibleTArray
<T
>& seq
);
1591 template<typename T
>
1592 void DoTraceSequence(JSTracer
* trc
, InfallibleTArray
<T
>& seq
);
1594 // Class for simple sequence arguments, only used internally by codegen.
1595 template<typename T
>
1596 class AutoSequence
: public AutoFallibleTArray
<T
, 16>
1599 AutoSequence() : AutoFallibleTArray
<T
, 16>()
1602 // Allow converting to const sequences as needed
1603 operator const Sequence
<T
>&() const {
1604 return *reinterpret_cast<const Sequence
<T
>*>(this);
1608 // Class used to trace sequences, with specializations for various
1610 template<typename T
,
1611 bool isDictionary
=IsBaseOf
<DictionaryBase
, T
>::value
,
1612 bool isTypedArray
=IsBaseOf
<AllTypedArraysBase
, T
>::value
>
1613 class SequenceTracer
1615 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1618 // sequence<object> or sequence<object?>
1620 class SequenceTracer
<JSObject
*, false, false>
1622 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1625 static void TraceSequence(JSTracer
* trc
, JSObject
** objp
, JSObject
** end
) {
1626 for (; objp
!= end
; ++objp
) {
1627 JS_CallObjectTracer(trc
, objp
, "sequence<object>");
1634 class SequenceTracer
<JS::Value
, false, false>
1636 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1639 static void TraceSequence(JSTracer
* trc
, JS::Value
* valp
, JS::Value
* end
) {
1640 for (; valp
!= end
; ++valp
) {
1641 JS_CallValueTracer(trc
, valp
, "sequence<any>");
1646 // sequence<sequence<T>>
1647 template<typename T
>
1648 class SequenceTracer
<Sequence
<T
>, false, false>
1650 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1653 static void TraceSequence(JSTracer
* trc
, Sequence
<T
>* seqp
, Sequence
<T
>* end
) {
1654 for (; seqp
!= end
; ++seqp
) {
1655 DoTraceSequence(trc
, *seqp
);
1660 // sequence<sequence<T>> as return value
1661 template<typename T
>
1662 class SequenceTracer
<nsTArray
<T
>, false, false>
1664 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1667 static void TraceSequence(JSTracer
* trc
, nsTArray
<T
>* seqp
, nsTArray
<T
>* end
) {
1668 for (; seqp
!= end
; ++seqp
) {
1669 DoTraceSequence(trc
, *seqp
);
1674 // sequence<someDictionary>
1675 template<typename T
>
1676 class SequenceTracer
<T
, true, false>
1678 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1681 static void TraceSequence(JSTracer
* trc
, T
* dictp
, T
* end
) {
1682 for (; dictp
!= end
; ++dictp
) {
1683 dictp
->TraceDictionary(trc
);
1688 // sequence<SomeTypedArray>
1689 template<typename T
>
1690 class SequenceTracer
<T
, false, true>
1692 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1695 static void TraceSequence(JSTracer
* trc
, T
* arrayp
, T
* end
) {
1696 for (; arrayp
!= end
; ++arrayp
) {
1697 arrayp
->TraceSelf(trc
);
1702 // sequence<T?> with T? being a Nullable<T>
1703 template<typename T
>
1704 class SequenceTracer
<Nullable
<T
>, false, false>
1706 explicit SequenceTracer() MOZ_DELETE
; // Should never be instantiated
1709 static void TraceSequence(JSTracer
* trc
, Nullable
<T
>* seqp
,
1711 for (; seqp
!= end
; ++seqp
) {
1712 if (!seqp
->IsNull()) {
1713 // Pretend like we actually have a length-one sequence here so
1714 // we can do template instantiation correctly for T.
1715 T
& val
= seqp
->Value();
1717 SequenceTracer
<T
>::TraceSequence(trc
, ptr
, ptr
+1);
1723 template<typename T
>
1724 void DoTraceSequence(JSTracer
* trc
, FallibleTArray
<T
>& seq
)
1726 SequenceTracer
<T
>::TraceSequence(trc
, seq
.Elements(),
1727 seq
.Elements() + seq
.Length());
1730 template<typename T
>
1731 void DoTraceSequence(JSTracer
* trc
, InfallibleTArray
<T
>& seq
)
1733 SequenceTracer
<T
>::TraceSequence(trc
, seq
.Elements(),
1734 seq
.Elements() + seq
.Length());
1737 // Rooter class for sequences; this is what we mostly use in the codegen
1738 template<typename T
>
1739 class MOZ_STACK_CLASS SequenceRooter
: private JS::CustomAutoRooter
1742 SequenceRooter(JSContext
*aCx
, FallibleTArray
<T
>* aSequence
1743 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
1744 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
1745 mFallibleArray(aSequence
),
1746 mSequenceType(eFallibleArray
)
1750 SequenceRooter(JSContext
*aCx
, InfallibleTArray
<T
>* aSequence
1751 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
1752 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
1753 mInfallibleArray(aSequence
),
1754 mSequenceType(eInfallibleArray
)
1758 SequenceRooter(JSContext
*aCx
, Nullable
<nsTArray
<T
> >* aSequence
1759 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
1760 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
1761 mNullableArray(aSequence
),
1762 mSequenceType(eNullableArray
)
1773 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
1775 if (mSequenceType
== eFallibleArray
) {
1776 DoTraceSequence(trc
, *mFallibleArray
);
1777 } else if (mSequenceType
== eInfallibleArray
) {
1778 DoTraceSequence(trc
, *mInfallibleArray
);
1780 MOZ_ASSERT(mSequenceType
== eNullableArray
);
1781 if (!mNullableArray
->IsNull()) {
1782 DoTraceSequence(trc
, mNullableArray
->Value());
1788 InfallibleTArray
<T
>* mInfallibleArray
;
1789 FallibleTArray
<T
>* mFallibleArray
;
1790 Nullable
<nsTArray
<T
> >* mNullableArray
;
1793 SequenceType mSequenceType
;
1796 template<typename T
>
1797 class MOZ_STACK_CLASS RootedUnion
: public T
,
1798 private JS::CustomAutoRooter
1801 RootedUnion(JSContext
* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM
) :
1803 JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
)
1807 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
1809 this->TraceUnion(trc
);
1813 template<typename T
>
1814 class MOZ_STACK_CLASS NullableRootedUnion
: public Nullable
<T
>,
1815 private JS::CustomAutoRooter
1818 NullableRootedUnion(JSContext
* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM
) :
1820 JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
)
1824 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
1826 if (!this->IsNull()) {
1827 this->Value().TraceUnion(trc
);
1833 IdEquals(jsid id
, const char* string
)
1835 return JSID_IS_STRING(id
) &&
1836 JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id
), string
);
1840 AddStringToIDVector(JSContext
* cx
, JS::AutoIdVector
& vector
, const char* name
)
1842 return vector
.growBy(1) &&
1843 InternJSString(cx
, vector
[vector
.length() - 1], name
);
1846 // Implementation of the bits that XrayWrapper needs
1849 * This resolves indexed or named properties of obj.
1851 * wrapper is the Xray JS object.
1852 * obj is the target object of the Xray, a binding's instance object or a
1853 * interface or interface prototype object.
1856 XrayResolveOwnProperty(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
1857 JS::Handle
<JSObject
*> obj
,
1858 JS::Handle
<jsid
> id
,
1859 JS::MutableHandle
<JSPropertyDescriptor
> desc
, unsigned flags
);
1862 * This resolves operations, attributes and constants of the interfaces for obj.
1864 * wrapper is the Xray JS object.
1865 * obj is the target object of the Xray, a binding's instance object or a
1866 * interface or interface prototype object.
1869 XrayResolveNativeProperty(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
1870 JS::Handle
<JSObject
*> obj
,
1871 JS::Handle
<jsid
> id
, JS::MutableHandle
<JSPropertyDescriptor
> desc
);
1874 * Define a property on obj through an Xray wrapper.
1876 * wrapper is the Xray JS object.
1877 * obj is the target object of the Xray, a binding's instance object or a
1878 * interface or interface prototype object.
1879 * defined will be set to true if a property was set as a result of this call.
1882 XrayDefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
1883 JS::Handle
<JSObject
*> obj
, JS::Handle
<jsid
> id
,
1884 JS::MutableHandle
<JSPropertyDescriptor
> desc
, bool* defined
);
1887 * This enumerates indexed or named properties of obj and operations, attributes
1888 * and constants of the interfaces for obj.
1890 * wrapper is the Xray JS object.
1891 * obj is the target object of the Xray, a binding's instance object or a
1892 * interface or interface prototype object.
1893 * flags are JSITER_* flags.
1896 XrayEnumerateProperties(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
1897 JS::Handle
<JSObject
*> obj
,
1898 unsigned flags
, JS::AutoIdVector
& props
);
1900 extern NativePropertyHooks sWorkerNativePropertyHooks
;
1902 // We use one constructor JSNative to represent all DOM interface objects (so
1903 // we can easily detect when we need to wrap them in an Xray wrapper). We store
1904 // the real JSNative in the mNative member of a JSNativeHolder in the
1905 // CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
1906 // specific interface object. We also store the NativeProperties in the
1907 // JSNativeHolder. The CONSTRUCTOR_XRAY_EXPANDO_SLOT is used to store the
1908 // expando chain of the Xray for the interface object.
1909 // Note that some interface objects are not yet a JSFunction but a normal
1910 // JSObject with a DOMJSClass, those do not use these slots.
1913 CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT
= 0,
1914 CONSTRUCTOR_XRAY_EXPANDO_SLOT
1918 Constructor(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
1921 UseDOMXray(JSObject
* obj
)
1923 const js::Class
* clasp
= js::GetObjectClass(obj
);
1924 return IsDOMClass(clasp
) ||
1925 IsDOMProxy(obj
, clasp
) ||
1926 JS_IsNativeFunction(obj
, Constructor
) ||
1927 IsDOMIfaceAndProtoClass(clasp
);
1932 HasConstructor(JSObject
* obj
)
1934 return JS_IsNativeFunction(obj
, Constructor
) ||
1935 js::GetObjectClass(obj
)->construct
;
1939 // Transfer reference in ptr to smartPtr.
1942 Take(nsRefPtr
<T
>& smartPtr
, T
* ptr
)
1944 smartPtr
= dont_AddRef(ptr
);
1947 // Transfer ownership of ptr to smartPtr.
1950 Take(nsAutoPtr
<T
>& smartPtr
, T
* ptr
)
1956 MustInheritFromNonRefcountedDOMObject(NonRefcountedDOMObject
*)
1960 // Set the chain of expando objects for various consumers of the given object.
1961 // For Paris Bindings only. See the relevant infrastructure in XrayWrapper.cpp.
1962 JSObject
* GetXrayExpandoChain(JSObject
*obj
);
1963 void SetXrayExpandoChain(JSObject
*obj
, JSObject
*chain
);
1966 * This creates a JSString containing the value that the toString function for
1967 * obj should create according to the WebIDL specification, ignoring any
1968 * modifications by script. The value is prefixed with pre and postfixed with
1969 * post, unless this is called for an object that has a stringifier. It is
1970 * specifically for use by Xray code.
1972 * wrapper is the Xray JS object.
1973 * obj is the target object of the Xray, a binding's instance object or a
1974 * interface or interface prototype object.
1975 * pre is a string that should be prefixed to the value.
1976 * post is a string that should be prefixed to the value.
1977 * v contains the JSString for the value if the function returns true.
1980 NativeToString(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
1981 JS::Handle
<JSObject
*> obj
, const char* pre
,
1983 JS::MutableHandle
<JS::Value
> v
);
1985 HAS_MEMBER(JSBindingFinalized
)
1987 template<class T
, bool hasCallback
=HasJSBindingFinalizedMember
<T
>::Value
>
1988 struct JSBindingFinalized
1990 static void Finalized(T
* self
)
1996 struct JSBindingFinalized
<T
, true>
1998 static void Finalized(T
* self
)
2000 self
->JSBindingFinalized();
2004 // Helpers for creating a const version of a type.
2005 template<typename T
>
2006 const T
& Constify(T
& arg
)
2011 // Helper for turning (Owning)NonNull<T> into T&
2012 template<typename T
>
2013 T
& NonNullHelper(T
& aArg
)
2018 template<typename T
>
2019 T
& NonNullHelper(NonNull
<T
>& aArg
)
2024 template<typename T
>
2025 const T
& NonNullHelper(const NonNull
<T
>& aArg
)
2030 template<typename T
>
2031 T
& NonNullHelper(OwningNonNull
<T
>& aArg
)
2036 template<typename T
>
2037 const T
& NonNullHelper(const OwningNonNull
<T
>& aArg
)
2042 // Reparent the wrapper of aObj to whatever its native now thinks its
2043 // parent should be.
2045 ReparentWrapper(JSContext
* aCx
, JS::Handle
<JSObject
*> aObj
);
2048 * Used to implement the hasInstance hook of an interface object.
2050 * instance should not be a security wrapper.
2053 InterfaceHasInstance(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
2054 JS::Handle
<JSObject
*> instance
,
2057 InterfaceHasInstance(JSContext
* cx
, JS::Handle
<JSObject
*> obj
, JS::MutableHandle
<JS::Value
> vp
,
2060 InterfaceHasInstance(JSContext
* cx
, int prototypeID
, int depth
,
2061 JS::Handle
<JSObject
*> instance
,
2064 // Helper for lenient getters/setters to report to console. If this
2065 // returns false, we couldn't even get a global.
2067 ReportLenientThisUnwrappingFailure(JSContext
* cx
, JSObject
* obj
);
2070 GetUnforgeableHolder(JSObject
* aGlobal
, prototypes::ID aId
)
2072 ProtoAndIfaceArray
& protoAndIfaceArray
= *GetProtoAndIfaceArray(aGlobal
);
2073 JSObject
* interfaceProto
= protoAndIfaceArray
[aId
];
2074 return &js::GetReservedSlot(interfaceProto
,
2075 DOM_INTERFACE_PROTO_SLOTS_BASE
).toObject();
2078 // Given a JSObject* that represents the chrome side of a JS-implemented WebIDL
2079 // interface, get the nsPIDOMWindow corresponding to the content side, if any.
2080 // A false return means an exception was thrown.
2082 GetWindowForJSImplementedObject(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
2083 nsPIDOMWindow
** window
);
2085 already_AddRefed
<nsPIDOMWindow
>
2086 ConstructJSImplementation(JSContext
* aCx
, const char* aContractId
,
2087 const GlobalObject
& aGlobal
,
2088 JS::MutableHandle
<JSObject
*> aObject
,
2092 * Convert an nsCString to jsval, returning true on success.
2093 * These functions are intended for ByteString implementations.
2094 * As such, the string is not UTF-8 encoded. Any UTF8 strings passed to these
2095 * methods will be mangled.
2097 bool NonVoidByteStringToJsval(JSContext
*cx
, const nsACString
&str
,
2098 JS::MutableHandle
<JS::Value
> rval
);
2099 inline bool ByteStringToJsval(JSContext
*cx
, const nsACString
&str
,
2100 JS::MutableHandle
<JS::Value
> rval
)
2106 return NonVoidByteStringToJsval(cx
, str
, rval
);
2109 template<class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2110 struct PreserveWrapperHelper
2112 static void PreserveWrapper(T
* aObject
)
2114 aObject
->PreserveWrapper(aObject
, NS_CYCLE_COLLECTION_PARTICIPANT(T
));
2119 struct PreserveWrapperHelper
<T
, true>
2121 static void PreserveWrapper(T
* aObject
)
2123 aObject
->PreserveWrapper(reinterpret_cast<nsISupports
*>(aObject
));
2128 void PreserveWrapper(T
* aObject
)
2130 PreserveWrapperHelper
<T
>::PreserveWrapper(aObject
);
2133 template<class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2134 struct CastingAssertions
2136 static bool ToSupportsIsCorrect(T
*)
2140 static bool ToSupportsIsOnPrimaryInheritanceChain(T
*, nsWrapperCache
*)
2147 struct CastingAssertions
<T
, true>
2149 static bool ToSupportsIsCorrect(T
* aObject
)
2151 return ToSupports(aObject
) == reinterpret_cast<nsISupports
*>(aObject
);
2153 static bool ToSupportsIsOnPrimaryInheritanceChain(T
* aObject
,
2154 nsWrapperCache
* aCache
)
2156 return reinterpret_cast<void*>(aObject
) != aCache
;
2162 ToSupportsIsCorrect(T
* aObject
)
2164 return CastingAssertions
<T
>::ToSupportsIsCorrect(aObject
);
2169 ToSupportsIsOnPrimaryInheritanceChain(T
* aObject
, nsWrapperCache
* aCache
)
2171 return CastingAssertions
<T
>::ToSupportsIsOnPrimaryInheritanceChain(aObject
,
2175 template<class T
, template <typename
> class SmartPtr
,
2176 bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2177 class DeferredFinalizer
2179 typedef nsTArray
<SmartPtr
<T
> > SmartPtrArray
;
2182 AppendDeferredFinalizePointer(void* aData
, void* aObject
)
2184 SmartPtrArray
* pointers
= static_cast<SmartPtrArray
*>(aData
);
2186 pointers
= new SmartPtrArray();
2189 T
* self
= static_cast<T
*>(aObject
);
2191 SmartPtr
<T
>* defer
= pointers
->AppendElement();
2196 DeferredFinalize(uint32_t aSlice
, void* aData
)
2198 MOZ_ASSERT(aSlice
> 0, "nonsensical/useless call with aSlice == 0");
2199 SmartPtrArray
* pointers
= static_cast<SmartPtrArray
*>(aData
);
2200 uint32_t oldLen
= pointers
->Length();
2201 if (oldLen
< aSlice
) {
2204 uint32_t newLen
= oldLen
- aSlice
;
2205 pointers
->RemoveElementsAt(newLen
, aSlice
);
2215 AddForDeferredFinalization(T
* aObject
)
2217 cyclecollector::DeferredFinalize(AppendDeferredFinalizePointer
,
2218 DeferredFinalize
, aObject
);
2222 template<class T
, template <typename
> class SmartPtr
>
2223 class DeferredFinalizer
<T
, SmartPtr
, true>
2227 AddForDeferredFinalization(T
* aObject
)
2229 cyclecollector::DeferredFinalize(reinterpret_cast<nsISupports
*>(aObject
));
2233 template<class T
, template <typename
> class SmartPtr
>
2235 AddForDeferredFinalization(T
* aObject
)
2237 DeferredFinalizer
<T
, SmartPtr
>::AddForDeferredFinalization(aObject
);
2240 // This returns T's CC participant if it participates in CC or null if it
2241 // doesn't. This also returns null for classes that don't inherit from
2242 // nsISupports (QI should be used to get the participant for those).
2243 template<class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2244 class GetCCParticipant
2246 // Helper for GetCCParticipant for classes that participate in CC.
2248 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2249 GetHelper(int, typename
U::NS_CYCLE_COLLECTION_INNERCLASS
* dummy
=nullptr)
2251 return T::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant();
2253 // Helper for GetCCParticipant for classes that don't participate in CC.
2255 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2262 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2265 // Passing int() here will try to call the GetHelper that takes an int as
2266 // its firt argument. If T doesn't participate in CC then substitution for
2267 // the second argument (with a default value) will fail and because of
2268 // SFINAE the next best match (the variant taking a double) will be called.
2269 return GetHelper
<T
>(int());
2274 class GetCCParticipant
<T
, true>
2277 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2285 ThreadsafeCheckIsChrome(JSContext
* aCx
, JSObject
* aObj
);
2288 TraceGlobal(JSTracer
* aTrc
, JSObject
* aObj
);
2291 FinalizeGlobal(JSFreeOp
* aFop
, JSObject
* aObj
);
2294 ResolveGlobal(JSContext
* aCx
, JS::Handle
<JSObject
*> aObj
,
2295 JS::MutableHandle
<jsid
> aId
, unsigned aFlags
,
2296 JS::MutableHandle
<JSObject
*> aObjp
);
2299 EnumerateGlobal(JSContext
* aCx
, JS::Handle
<JSObject
*> aObj
);
2301 template <class T
, JS::Handle
<JSObject
*> (*ProtoGetter
)(JSContext
*,
2302 JS::Handle
<JSObject
*>)>
2304 CreateGlobal(JSContext
* aCx
, T
* aObject
, nsWrapperCache
* aCache
,
2305 const JSClass
* aClass
, JS::CompartmentOptions
& aOptions
,
2306 JSPrincipals
* aPrincipal
)
2308 MOZ_ASSERT(!NS_IsMainThread());
2310 JS::Rooted
<JSObject
*> global(aCx
,
2311 JS_NewGlobalObject(aCx
, aClass
, aPrincipal
, JS::DontFireOnNewGlobalHook
,
2314 NS_WARNING("Failed to create global");
2318 JSAutoCompartment
ac(aCx
, global
);
2320 dom::AllocateProtoAndIfaceCache(global
);
2322 js::SetReservedSlot(global
, DOM_OBJECT_SLOT
, PRIVATE_TO_JSVAL(aObject
));
2325 aCache
->SetIsDOMBinding();
2326 aCache
->SetWrapper(global
);
2328 /* Intl API is broken and makes this fail intermittently, see bug 934889.
2329 if (!JS_InitStandardClasses(aCx, global)) {
2330 NS_WARNING("Failed to init standard classes");
2335 JS::Handle
<JSObject
*> proto
= ProtoGetter(aCx
, global
);
2336 NS_ENSURE_TRUE(proto
, nullptr);
2338 if (!JS_SetPrototype(aCx
, global
, proto
)) {
2339 NS_WARNING("Failed to set proto");
2343 mozilla::HoldJSObjects(aObject
);
2349 } // namespace mozilla
2351 #endif /* mozilla_dom_BindingUtils_h__ */