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/ArrayUtils.h"
13 #include "mozilla/Alignment.h"
14 #include "mozilla/Array.h"
15 #include "mozilla/Assertions.h"
16 #include "mozilla/dom/BindingDeclarations.h"
17 #include "mozilla/dom/CallbackObject.h"
18 #include "mozilla/dom/DOMJSClass.h"
19 #include "mozilla/dom/DOMJSProxyHandler.h"
20 #include "mozilla/dom/Exceptions.h"
21 #include "mozilla/dom/NonRefcountedDOMObject.h"
22 #include "mozilla/dom/Nullable.h"
23 #include "mozilla/dom/RootedDictionary.h"
24 #include "mozilla/dom/workers/Workers.h"
25 #include "mozilla/ErrorResult.h"
26 #include "mozilla/Likely.h"
27 #include "mozilla/MemoryReporting.h"
28 #include "mozilla/CycleCollectedJSRuntime.h"
29 #include "nsCycleCollector.h"
30 #include "nsIXPConnect.h"
31 #include "nsJSUtils.h"
32 #include "nsISupportsImpl.h"
33 #include "qsObjectHelper.h"
34 #include "xpcpublic.h"
35 #include "nsIVariant.h"
36 #include "pldhash.h" // For PLDHashOperator
38 #include "nsWrapperCacheInlines.h"
45 template<typename DataType
> class MozMap
;
49 SelfRef() : ptr(nullptr) {}
50 explicit SelfRef(nsISupports
*p
) : ptr(p
) {}
51 ~SelfRef() { NS_IF_RELEASE(ptr
); }
57 UnwrapArgImpl(JS::Handle
<JSObject
*> src
, const nsIID
& iid
, void** ppArg
);
59 /** Convert a jsval to an XPCOM pointer. */
60 template <class Interface
>
62 UnwrapArg(JS::Handle
<JSObject
*> src
, Interface
** ppArg
)
64 return UnwrapArgImpl(src
, NS_GET_TEMPLATE_IID(Interface
),
65 reinterpret_cast<void**>(ppArg
));
69 GetInvalidThisErrorForMethod(bool aSecurityError
)
71 return aSecurityError
? MSG_METHOD_THIS_UNWRAPPING_DENIED
:
72 MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE
;
76 GetInvalidThisErrorForGetter(bool aSecurityError
)
78 return aSecurityError
? MSG_GETTER_THIS_UNWRAPPING_DENIED
:
79 MSG_GETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE
;
83 GetInvalidThisErrorForSetter(bool aSecurityError
)
85 return aSecurityError
? MSG_SETTER_THIS_UNWRAPPING_DENIED
:
86 MSG_SETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE
;
90 ThrowInvalidThis(JSContext
* aCx
, const JS::CallArgs
& aArgs
,
91 const ErrNum aErrorNumber
,
92 const char* aInterfaceName
);
95 ThrowInvalidThis(JSContext
* aCx
, const JS::CallArgs
& aArgs
,
96 const ErrNum aErrorNumber
,
97 prototypes::ID aProtoId
);
100 ThrowMethodFailedWithDetails(JSContext
* cx
, ErrorResult
& rv
,
101 const char* ifaceName
,
102 const char* memberName
,
103 bool reportJSContentExceptions
= false)
105 if (rv
.IsTypeError()) {
106 rv
.ReportTypeError(cx
);
109 if (rv
.IsJSException()) {
110 if (reportJSContentExceptions
) {
111 rv
.ReportJSExceptionFromJSImplementation(cx
);
113 rv
.ReportJSException(cx
);
117 if (rv
.IsNotEnoughArgsError()) {
118 rv
.ReportNotEnoughArgsError(cx
, ifaceName
, memberName
);
121 return Throw(cx
, rv
.ErrorCode());
124 // Returns true if the JSClass is used for DOM objects.
126 IsDOMClass(const JSClass
* clasp
)
128 return clasp
->flags
& JSCLASS_IS_DOMJSCLASS
;
132 IsDOMClass(const js::Class
* clasp
)
134 return IsDOMClass(Jsvalify(clasp
));
137 // Return true if the JSClass is used for non-proxy DOM objects.
139 IsNonProxyDOMClass(const js::Class
* clasp
)
141 return IsDOMClass(clasp
) && !clasp
->isProxy();
145 IsNonProxyDOMClass(const JSClass
* clasp
)
147 return IsNonProxyDOMClass(js::Valueify(clasp
));
150 // Returns true if the JSClass is used for DOM interface and interface
151 // prototype objects.
153 IsDOMIfaceAndProtoClass(const JSClass
* clasp
)
155 return clasp
->flags
& JSCLASS_IS_DOMIFACEANDPROTOJSCLASS
;
159 IsDOMIfaceAndProtoClass(const js::Class
* clasp
)
161 return IsDOMIfaceAndProtoClass(Jsvalify(clasp
));
164 static_assert(DOM_OBJECT_SLOT
== 0,
165 "DOM_OBJECT_SLOT doesn't match the proxy private slot. "
166 "Expect bad things");
169 UnwrapDOMObject(JSObject
* obj
)
171 MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj
)),
172 "Don't pass non-DOM objects to this function");
174 JS::Value val
= js::GetReservedOrProxyPrivateSlot(obj
, DOM_OBJECT_SLOT
);
175 return static_cast<T
*>(val
.toPrivate());
180 UnwrapPossiblyNotInitializedDOMObject(JSObject
* obj
)
182 // This is used by the OjectMoved JSClass hook which can be called before
183 // JS_NewObject has returned and so before we have a chance to set
184 // DOM_OBJECT_SLOT to anything useful.
186 MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj
)),
187 "Don't pass non-DOM objects to this function");
189 JS::Value val
= js::GetReservedOrProxyPrivateSlot(obj
, DOM_OBJECT_SLOT
);
190 if (val
.isUndefined()) {
193 return static_cast<T
*>(val
.toPrivate());
196 inline const DOMJSClass
*
197 GetDOMClass(const js::Class
* clasp
)
199 return IsDOMClass(clasp
) ? DOMJSClass::FromJSClass(clasp
) : nullptr;
202 inline const DOMJSClass
*
203 GetDOMClass(JSObject
* obj
)
205 return GetDOMClass(js::GetObjectClass(obj
));
209 UnwrapDOMObjectToISupports(JSObject
* aObject
)
211 const DOMJSClass
* clasp
= GetDOMClass(aObject
);
212 if (!clasp
|| !clasp
->mDOMObjectIsISupports
) {
216 return UnwrapDOMObject
<nsISupports
>(aObject
);
220 IsDOMObject(JSObject
* obj
)
222 return IsDOMClass(js::GetObjectClass(obj
));
225 #define UNWRAP_OBJECT(Interface, obj, value) \
226 mozilla::dom::UnwrapObject<mozilla::dom::prototypes::id::Interface, \
227 mozilla::dom::Interface##Binding::NativeType>(obj, value)
229 // Some callers don't want to set an exception when unwrapping fails
230 // (for example, overload resolution uses unwrapping to tell what sort
231 // of thing it's looking at).
232 // U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
233 template <class T
, typename U
>
234 MOZ_ALWAYS_INLINE nsresult
235 UnwrapObject(JSObject
* obj
, U
& value
, prototypes::ID protoID
,
238 /* First check to see whether we have a DOM object */
239 const DOMJSClass
* domClass
= GetDOMClass(obj
);
241 /* Maybe we have a security wrapper or outer window? */
242 if (!js::IsWrapper(obj
)) {
243 /* Not a DOM object, not a wrapper, just bail */
244 return NS_ERROR_XPC_BAD_CONVERT_JS
;
247 obj
= js::CheckedUnwrap(obj
, /* stopAtOuter = */ false);
249 return NS_ERROR_XPC_SECURITY_MANAGER_VETO
;
251 MOZ_ASSERT(!js::IsWrapper(obj
));
252 domClass
= GetDOMClass(obj
);
254 /* We don't have a DOM object */
255 return NS_ERROR_XPC_BAD_CONVERT_JS
;
259 /* This object is a DOM object. Double-check that it is safely
260 castable to T by checking whether it claims to inherit from the
261 class identified by protoID. */
262 if (domClass
->mInterfaceChain
[protoDepth
] == protoID
) {
263 value
= UnwrapDOMObject
<T
>(obj
);
267 /* It's the wrong sort of DOM object */
268 return NS_ERROR_XPC_BAD_CONVERT_JS
;
271 template <prototypes::ID PrototypeID
, class T
, typename U
>
272 MOZ_ALWAYS_INLINE nsresult
273 UnwrapObject(JSObject
* obj
, U
& value
)
275 return UnwrapObject
<T
>(obj
, value
, PrototypeID
,
276 PrototypeTraits
<PrototypeID
>::Depth
);
280 IsNotDateOrRegExp(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
283 return !JS_ObjectIsDate(cx
, obj
) && !JS_ObjectIsRegExp(cx
, obj
);
286 MOZ_ALWAYS_INLINE
bool
287 IsObjectValueConvertibleToDictionary(JSContext
* cx
,
288 JS::Handle
<JS::Value
> objVal
)
290 JS::Rooted
<JSObject
*> obj(cx
, &objVal
.toObject());
291 return IsNotDateOrRegExp(cx
, obj
);
294 MOZ_ALWAYS_INLINE
bool
295 IsConvertibleToDictionary(JSContext
* cx
, JS::Handle
<JS::Value
> val
)
297 return val
.isNullOrUndefined() ||
298 (val
.isObject() && IsObjectValueConvertibleToDictionary(cx
, val
));
301 MOZ_ALWAYS_INLINE
bool
302 IsConvertibleToCallbackInterface(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
304 return IsNotDateOrRegExp(cx
, obj
);
307 // The items in the protoAndIfaceCache are indexed by the prototypes::id::ID,
308 // constructors::id::ID and namedpropertiesobjects::id::ID enums, in that order.
309 // The end of the prototype objects should be the start of the interface
310 // objects, and the end of the interface objects should be the start of the
311 // named properties objects.
312 static_assert((size_t)constructors::id::_ID_Start
==
313 (size_t)prototypes::id::_ID_Count
&&
314 (size_t)namedpropertiesobjects::id::_ID_Start
==
315 (size_t)constructors::id::_ID_Count
,
316 "Overlapping or discontiguous indexes.");
317 const size_t kProtoAndIfaceCacheCount
= namedpropertiesobjects::id::_ID_Count
;
319 class ProtoAndIfaceCache
321 // The caching strategy we use depends on what sort of global we're dealing
322 // with. For a window-like global, we want everything to be as fast as
323 // possible, so we use a flat array, indexed by prototype/constructor ID.
324 // For everything else (e.g. globals for JSMs), space is more important than
325 // speed, so we use a two-level lookup table.
327 class ArrayCache
: public Array
<JS::Heap
<JSObject
*>, kProtoAndIfaceCacheCount
>
330 JSObject
* EntrySlotIfExists(size_t i
) {
334 JS::Heap
<JSObject
*>& EntrySlotOrCreate(size_t i
) {
338 JS::Heap
<JSObject
*>& EntrySlotMustExist(size_t i
) {
339 MOZ_ASSERT((*this)[i
]);
343 void Trace(JSTracer
* aTracer
) {
344 for (size_t i
= 0; i
< ArrayLength(*this); ++i
) {
346 JS_CallObjectTracer(aTracer
, &(*this)[i
], "protoAndIfaceCache[i]");
351 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
352 return aMallocSizeOf(this);
360 memset(&mPages
, 0, sizeof(mPages
));
364 for (size_t i
= 0; i
< ArrayLength(mPages
); ++i
) {
369 JSObject
* EntrySlotIfExists(size_t i
) {
370 MOZ_ASSERT(i
< kProtoAndIfaceCacheCount
);
371 size_t pageIndex
= i
/ kPageSize
;
372 size_t leafIndex
= i
% kPageSize
;
373 Page
* p
= mPages
[pageIndex
];
377 return (*p
)[leafIndex
];
380 JS::Heap
<JSObject
*>& EntrySlotOrCreate(size_t i
) {
381 MOZ_ASSERT(i
< kProtoAndIfaceCacheCount
);
382 size_t pageIndex
= i
/ kPageSize
;
383 size_t leafIndex
= i
% kPageSize
;
384 Page
* p
= mPages
[pageIndex
];
387 mPages
[pageIndex
] = p
;
389 return (*p
)[leafIndex
];
392 JS::Heap
<JSObject
*>& EntrySlotMustExist(size_t i
) {
393 MOZ_ASSERT(i
< kProtoAndIfaceCacheCount
);
394 size_t pageIndex
= i
/ kPageSize
;
395 size_t leafIndex
= i
% kPageSize
;
396 Page
* p
= mPages
[pageIndex
];
398 return (*p
)[leafIndex
];
401 void Trace(JSTracer
* trc
) {
402 for (size_t i
= 0; i
< ArrayLength(mPages
); ++i
) {
405 for (size_t j
= 0; j
< ArrayLength(*p
); ++j
) {
407 JS_CallObjectTracer(trc
, &(*p
)[j
], "protoAndIfaceCache[i]");
414 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
415 size_t n
= aMallocSizeOf(this);
416 for (size_t i
= 0; i
< ArrayLength(mPages
); ++i
) {
417 n
+= aMallocSizeOf(mPages
[i
]);
423 static const size_t kPageSize
= 16;
424 typedef Array
<JS::Heap
<JSObject
*>, kPageSize
> Page
;
425 static const size_t kNPages
= kProtoAndIfaceCacheCount
/ kPageSize
+
426 size_t(bool(kProtoAndIfaceCacheCount
% kPageSize
));
427 Array
<Page
*, kNPages
> mPages
;
436 explicit ProtoAndIfaceCache(Kind aKind
) : mKind(aKind
) {
437 MOZ_COUNT_CTOR(ProtoAndIfaceCache
);
438 if (aKind
== WindowLike
) {
439 mArrayCache
= new ArrayCache();
441 mPageTableCache
= new PageTableCache();
445 ~ProtoAndIfaceCache() {
446 if (mKind
== WindowLike
) {
449 delete mPageTableCache
;
451 MOZ_COUNT_DTOR(ProtoAndIfaceCache
);
454 #define FORWARD_OPERATION(opName, args) \
456 if (mKind == WindowLike) { \
457 return mArrayCache->opName args; \
459 return mPageTableCache->opName args; \
463 JSObject
* EntrySlotIfExists(size_t i
) {
464 FORWARD_OPERATION(EntrySlotIfExists
, (i
));
467 JS::Heap
<JSObject
*>& EntrySlotOrCreate(size_t i
) {
468 FORWARD_OPERATION(EntrySlotOrCreate
, (i
));
471 JS::Heap
<JSObject
*>& EntrySlotMustExist(size_t i
) {
472 FORWARD_OPERATION(EntrySlotMustExist
, (i
));
475 void Trace(JSTracer
*aTracer
) {
476 FORWARD_OPERATION(Trace
, (aTracer
));
479 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf
) {
480 size_t n
= aMallocSizeOf(this);
481 n
+= (mKind
== WindowLike
482 ? mArrayCache
->SizeOfIncludingThis(aMallocSizeOf
)
483 : mPageTableCache
->SizeOfIncludingThis(aMallocSizeOf
));
486 #undef FORWARD_OPERATION
490 ArrayCache
*mArrayCache
;
491 PageTableCache
*mPageTableCache
;
497 AllocateProtoAndIfaceCache(JSObject
* obj
, ProtoAndIfaceCache::Kind aKind
)
499 MOZ_ASSERT(js::GetObjectClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
);
500 MOZ_ASSERT(js::GetReservedSlot(obj
, DOM_PROTOTYPE_SLOT
).isUndefined());
502 ProtoAndIfaceCache
* protoAndIfaceCache
= new ProtoAndIfaceCache(aKind
);
504 js::SetReservedSlot(obj
, DOM_PROTOTYPE_SLOT
,
505 JS::PrivateValue(protoAndIfaceCache
));
510 VerifyTraceProtoAndIfaceCacheCalled(JSTracer
*trc
, void **thingp
,
513 struct VerifyTraceProtoAndIfaceCacheCalledTracer
: public JSTracer
517 explicit VerifyTraceProtoAndIfaceCacheCalledTracer(JSRuntime
*rt
)
518 : JSTracer(rt
, VerifyTraceProtoAndIfaceCacheCalled
), ok(false)
524 TraceProtoAndIfaceCache(JSTracer
* trc
, JSObject
* obj
)
526 MOZ_ASSERT(js::GetObjectClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
);
529 if (trc
->callback
== VerifyTraceProtoAndIfaceCacheCalled
) {
530 // We don't do anything here, we only want to verify that
531 // TraceProtoAndIfaceCache was called.
532 static_cast<VerifyTraceProtoAndIfaceCacheCalledTracer
*>(trc
)->ok
= true;
537 if (!HasProtoAndIfaceCache(obj
))
539 ProtoAndIfaceCache
* protoAndIfaceCache
= GetProtoAndIfaceCache(obj
);
540 protoAndIfaceCache
->Trace(trc
);
544 DestroyProtoAndIfaceCache(JSObject
* obj
)
546 MOZ_ASSERT(js::GetObjectClass(obj
)->flags
& JSCLASS_DOM_GLOBAL
);
548 ProtoAndIfaceCache
* protoAndIfaceCache
= GetProtoAndIfaceCache(obj
);
550 delete protoAndIfaceCache
;
554 * Add constants to an object.
557 DefineConstants(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
558 const ConstantSpec
* cs
);
560 struct JSNativeHolder
563 const NativePropertyHooks
* mPropertyHooks
;
566 struct NamedConstructor
569 const JSNativeHolder mHolder
;
574 * Create a DOM interface object (if constructorClass is non-null) and/or a
575 * DOM interface prototype object (if protoClass is non-null).
577 * global is used as the parent of the interface object and the interface
579 * protoProto is the prototype to use for the interface prototype object.
580 * interfaceProto is the prototype to use for the interface object.
581 * protoClass is the JSClass to use for the interface prototype object.
582 * This is null if we should not create an interface prototype
584 * protoCache a pointer to a JSObject pointer where we should cache the
585 * interface prototype object. This must be null if protoClass is and
587 * constructorClass is the JSClass to use for the interface object.
588 * This is null if we should not create an interface object or
589 * if it should be a function object.
590 * constructor holds the JSNative to back the interface object which should be a
591 * Function, unless constructorClass is non-null in which case it is
592 * ignored. If this is null and constructorClass is also null then
593 * we should not create an interface object at all.
594 * ctorNargs is the length of the constructor function; 0 if no constructor
595 * constructorCache a pointer to a JSObject pointer where we should cache the
596 * interface object. This must be null if both constructorClass
597 * and constructor are null, and non-null otherwise.
598 * properties contains the methods, attributes and constants to be defined on
599 * objects in any compartment.
600 * chromeProperties contains the methods, attributes and constants to be defined
601 * on objects in chrome compartments. This must be null if the
602 * interface doesn't have any ChromeOnly properties or if the
603 * object is being created in non-chrome compartment.
604 * defineOnGlobal controls whether properties should be defined on the given
605 * global for the interface object (if any) and named
606 * constructors (if any) for this interface. This can be
607 * false in situations where we want the properties to only
608 * appear on privileged Xrays but not on the unprivileged
611 * At least one of protoClass, constructorClass or constructor should be
612 * non-null. If constructorClass or constructor are non-null, the resulting
613 * interface object will be defined on the given global with property name
614 * |name|, which must also be non-null.
617 CreateInterfaceObjects(JSContext
* cx
, JS::Handle
<JSObject
*> global
,
618 JS::Handle
<JSObject
*> protoProto
,
619 const js::Class
* protoClass
, JS::Heap
<JSObject
*>* protoCache
,
620 JS::Handle
<JSObject
*> interfaceProto
,
621 const js::Class
* constructorClass
, const JSNativeHolder
* constructor
,
622 unsigned ctorNargs
, const NamedConstructor
* namedConstructors
,
623 JS::Heap
<JSObject
*>* constructorCache
,
624 const NativeProperties
* regularProperties
,
625 const NativeProperties
* chromeOnlyProperties
,
626 const char* name
, bool defineOnGlobal
);
629 * Define the properties (regular and chrome-only) on obj.
631 * obj the object to instal the properties on. This should be the interface
632 * prototype object for regular interfaces and the instance object for
633 * interfaces marked with Global.
634 * properties contains the methods, attributes and constants to be defined on
635 * objects in any compartment.
636 * chromeProperties contains the methods, attributes and constants to be defined
637 * on objects in chrome compartments. This must be null if the
638 * interface doesn't have any ChromeOnly properties or if the
639 * object is being created in non-chrome compartment.
642 DefineProperties(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
643 const NativeProperties
* properties
,
644 const NativeProperties
* chromeOnlyProperties
);
647 * Define the unforgeable methods on an object.
650 DefineUnforgeableMethods(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
651 const Prefable
<const JSFunctionSpec
>* props
);
654 * Define the unforgeable attributes on an object.
657 DefineUnforgeableAttributes(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
658 const Prefable
<const JSPropertySpec
>* props
);
661 DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(JSContext
* cx
,
662 JS::Handle
<JSObject
*> obj
,
663 const NativeProperties
* properties
);
666 DefineWebIDLBindingPropertiesOnXPCObject(JSContext
* cx
,
667 JS::Handle
<JSObject
*> obj
,
668 const NativeProperties
* properties
);
671 #define HAS_MEMBER_CHECK(_name) \
672 template<typename V> static yes& Check(char (*)[(&V::_name == 0) + 1])
674 #define HAS_MEMBER_CHECK(_name) \
675 template<typename V> static yes& Check(char (*)[sizeof(&V::_name) + 1])
678 #define HAS_MEMBER(_name) \
679 template<typename T> \
680 class Has##_name##Member { \
681 typedef char yes[1]; \
682 typedef char no[2]; \
683 HAS_MEMBER_CHECK(_name); \
684 template<typename V> static no& Check(...); \
687 static bool const Value = sizeof(Check<T>(nullptr)) == sizeof(yes); \
690 HAS_MEMBER(WrapObject
)
692 // HasWrapObject<T>::Value will be true if T has a WrapObject member but it's
693 // not nsWrapperCache::WrapObject.
700 typedef JSObject
* (nsWrapperCache::*WrapObject
)(JSContext
*,
701 JS::Handle
<JSObject
*>);
702 template<typename U
, U
> struct SFINAE
;
703 template <typename V
> static no
& Check(SFINAE
<WrapObject
, &V::WrapObject
>*);
704 template <typename V
> static yes
& Check(...);
707 static bool const Value
= HasWrapObjectMember
<T
>::Value
&&
708 sizeof(Check
<T
>(nullptr)) == sizeof(yes
);
712 template <class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
714 CheckWrapperCacheCast
718 return reinterpret_cast<uintptr_t>(
719 static_cast<nsWrapperCache
*>(
720 reinterpret_cast<T
*>(1))) == 1;
725 CheckWrapperCacheCast
<T
, true>
734 MOZ_ALWAYS_INLINE
bool
735 CouldBeDOMBinding(void*)
740 MOZ_ALWAYS_INLINE
bool
741 CouldBeDOMBinding(nsWrapperCache
* aCache
)
743 return aCache
->IsDOMBinding();
747 TryToOuterize(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
749 if (js::IsInnerObject(&rval
.toObject())) {
750 JS::Rooted
<JSObject
*> obj(cx
, &rval
.toObject());
751 obj
= JS_ObjectToOuterObject(cx
, obj
);
756 rval
.set(JS::ObjectValue(*obj
));
762 // Make sure to wrap the given string value into the right compartment, as
766 MaybeWrapStringValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
768 MOZ_ASSERT(rval
.isString());
769 JSString
* str
= rval
.toString();
770 if (JS::GetTenuredGCThingZone(str
) != js::GetContextZone(cx
)) {
771 return JS_WrapValue(cx
, rval
);
776 // Make sure to wrap the given object value into the right compartment as
777 // needed. This will work correctly, but possibly slowly, on all objects.
780 MaybeWrapObjectValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
782 MOZ_ASSERT(rval
.isObject());
784 // Cross-compartment always requires wrapping.
785 JSObject
* obj
= &rval
.toObject();
786 if (js::GetObjectCompartment(obj
) != js::GetContextCompartment(cx
)) {
787 return JS_WrapValue(cx
, rval
);
790 // We're same-compartment, but even then we might need to wrap
791 // objects specially. Check for that.
792 if (IsDOMObject(obj
)) {
793 return TryToOuterize(cx
, rval
);
796 // It's not a WebIDL object. But it might be an XPConnect one, in which case
797 // we may need to outerize here, so make sure to call JS_WrapValue.
798 return JS_WrapValue(cx
, rval
);
801 // Like MaybeWrapObjectValue, but also allows null
804 MaybeWrapObjectOrNullValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
806 MOZ_ASSERT(rval
.isObjectOrNull());
810 return MaybeWrapObjectValue(cx
, rval
);
813 // Wrapping for objects that are known to not be DOM or XPConnect objects
816 MaybeWrapNonDOMObjectValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
818 MOZ_ASSERT(rval
.isObject());
819 MOZ_ASSERT(!GetDOMClass(&rval
.toObject()));
820 MOZ_ASSERT(!(js::GetObjectClass(&rval
.toObject())->flags
&
821 JSCLASS_PRIVATE_IS_NSISUPPORTS
));
823 JSObject
* obj
= &rval
.toObject();
824 if (js::GetObjectCompartment(obj
) == js::GetContextCompartment(cx
)) {
827 return JS_WrapValue(cx
, rval
);
830 // Like MaybeWrapNonDOMObjectValue but allows null
833 MaybeWrapNonDOMObjectOrNullValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
835 MOZ_ASSERT(rval
.isObjectOrNull());
839 return MaybeWrapNonDOMObjectValue(cx
, rval
);
842 // If rval is a gcthing and is not in the compartment of cx, wrap rval
843 // into the compartment of cx (typically by replacing it with an Xray or
844 // cross-compartment wrapper around the original object).
845 MOZ_ALWAYS_INLINE
bool
846 MaybeWrapValue(JSContext
* cx
, JS::MutableHandle
<JS::Value
> rval
)
848 if (rval
.isString()) {
849 return MaybeWrapStringValue(cx
, rval
);
852 if (!rval
.isObject()) {
856 return MaybeWrapObjectValue(cx
, rval
);
859 namespace binding_detail
{
860 enum GetOrCreateReflectorWrapBehavior
{
861 eWrapIntoContextCompartment
,
862 eDontWrapIntoContextCompartment
866 struct TypeNeedsOuterization
868 // We only need to outerize Window objects, so anything inheriting from
869 // nsGlobalWindow (which inherits from EventTarget itself).
870 static const bool value
=
871 IsBaseOf
<nsGlobalWindow
, T
>::value
|| IsSame
<EventTarget
, T
>::value
;
874 template <class T
, GetOrCreateReflectorWrapBehavior wrapBehavior
>
875 MOZ_ALWAYS_INLINE
bool
876 DoGetOrCreateDOMReflector(JSContext
* cx
, T
* value
,
877 JS::MutableHandle
<JS::Value
> rval
)
880 JSObject
* obj
= value
->GetWrapperPreserveColor();
881 // We can get rid of this when we remove support for hasXPConnectImpls.
882 bool couldBeDOMBinding
= CouldBeDOMBinding(value
);
884 JS::ExposeObjectToActiveJS(obj
);
886 // Inline this here while we have non-dom objects in wrapper caches.
887 if (!couldBeDOMBinding
) {
891 obj
= value
->WrapObject(cx
);
893 // At this point, obj is null, so just return false.
894 // Callers seem to be testing JS_IsExceptionPending(cx) to
895 // figure out whether WrapObject() threw.
901 const DOMJSClass
* clasp
= GetDOMClass(obj
);
902 // clasp can be null if the cache contained a non-DOM object.
904 // Some sanity asserts about our object. Specifically:
905 // 1) If our class claims we're nsISupports, we better be nsISupports
906 // XXXbz ideally, we could assert that reinterpret_cast to nsISupports
907 // does the right thing, but I don't see a way to do it. :(
908 // 2) If our class doesn't claim we're nsISupports we better be
909 // reinterpret_castable to nsWrapperCache.
910 MOZ_ASSERT(clasp
, "What happened here?");
911 MOZ_ASSERT_IF(clasp
->mDOMObjectIsISupports
, (IsBaseOf
<nsISupports
, T
>::value
));
912 MOZ_ASSERT(CheckWrapperCacheCast
<T
>::Check());
916 rval
.set(JS::ObjectValue(*obj
));
918 bool sameCompartment
=
919 js::GetObjectCompartment(obj
) == js::GetContextCompartment(cx
);
920 if (sameCompartment
&& couldBeDOMBinding
) {
921 return TypeNeedsOuterization
<T
>::value
? TryToOuterize(cx
, rval
) : true;
924 if (wrapBehavior
== eDontWrapIntoContextCompartment
) {
925 if (TypeNeedsOuterization
<T
>::value
) {
926 JSAutoCompartment
ac(cx
, obj
);
927 return TryToOuterize(cx
, rval
);
933 return JS_WrapValue(cx
, rval
);
935 } // namespace binding_detail
937 // Create a JSObject wrapping "value", if there isn't one already, and store it
938 // in rval. "value" must be a concrete class that implements a
939 // GetWrapperPreserveColor() which can return its existing wrapper, if any, and
940 // a WrapObject() which will try to create a wrapper. Typically, this is done by
941 // having "value" inherit from nsWrapperCache.
943 // The value stored in rval will be ready to be exposed to whatever JS
944 // is running on cx right now. In particular, it will be in the
945 // compartment of cx, and outerized as needed.
947 MOZ_ALWAYS_INLINE
bool
948 GetOrCreateDOMReflector(JSContext
* cx
, T
* value
,
949 JS::MutableHandle
<JS::Value
> rval
)
951 using namespace binding_detail
;
952 return DoGetOrCreateDOMReflector
<T
, eWrapIntoContextCompartment
>(cx
, value
,
956 // Like GetOrCreateDOMReflector but doesn't wrap into the context compartment,
957 // and hence does not actually require cx to be in a compartment.
959 MOZ_ALWAYS_INLINE
bool
960 GetOrCreateDOMReflectorNoWrap(JSContext
* cx
, T
* value
,
961 JS::MutableHandle
<JS::Value
> rval
)
963 using namespace binding_detail
;
964 return DoGetOrCreateDOMReflector
<T
, eDontWrapIntoContextCompartment
>(cx
,
969 // Create a JSObject wrapping "value", for cases when "value" is a
970 // non-wrapper-cached object using WebIDL bindings. "value" must implement a
971 // WrapObject() method taking a JSContext and a scope.
974 WrapNewBindingNonWrapperCachedObject(JSContext
* cx
,
975 JS::Handle
<JSObject
*> scopeArg
,
977 JS::MutableHandle
<JS::Value
> rval
)
980 // We try to wrap in the compartment of the underlying object of "scope"
981 JS::Rooted
<JSObject
*> obj(cx
);
983 // scope for the JSAutoCompartment so that we restore the compartment
984 // before we call JS_WrapValue.
985 Maybe
<JSAutoCompartment
> ac
;
986 // Maybe<Handle> doesn't so much work, and in any case, adding
987 // more Maybe (one for a Rooted and one for a Handle) adds more
988 // code (and branches!) than just adding a single rooted.
989 JS::Rooted
<JSObject
*> scope(cx
, scopeArg
);
990 if (js::IsWrapper(scope
)) {
991 scope
= js::CheckedUnwrap(scope
, /* stopAtOuter = */ false);
994 ac
.emplace(cx
, scope
);
997 MOZ_ASSERT(js::IsObjectInContextCompartment(scope
, cx
));
998 obj
= value
->WrapObject(cx
);
1005 // We can end up here in all sorts of compartments, per above. Make
1006 // sure to JS_WrapValue!
1007 rval
.set(JS::ObjectValue(*obj
));
1008 return JS_WrapValue(cx
, rval
);
1011 // Create a JSObject wrapping "value", for cases when "value" is a
1012 // non-wrapper-cached owned object using WebIDL bindings. "value" must implement a
1013 // WrapObject() method taking a JSContext, a scope, and a boolean outparam that
1014 // is true if the JSObject took ownership
1017 WrapNewBindingNonWrapperCachedOwnedObject(JSContext
* cx
,
1018 JS::Handle
<JSObject
*> scopeArg
,
1019 nsAutoPtr
<T
>& value
,
1020 JS::MutableHandle
<JS::Value
> rval
)
1022 // We do a runtime check on value, because otherwise we might in
1023 // fact end up wrapping a null and invoking methods on it later.
1025 NS_RUNTIMEABORT("Don't try to wrap null objects");
1027 // We try to wrap in the compartment of the underlying object of "scope"
1028 JS::Rooted
<JSObject
*> obj(cx
);
1030 // scope for the JSAutoCompartment so that we restore the compartment
1031 // before we call JS_WrapValue.
1032 Maybe
<JSAutoCompartment
> ac
;
1033 // Maybe<Handle> doesn't so much work, and in any case, adding
1034 // more Maybe (one for a Rooted and one for a Handle) adds more
1035 // code (and branches!) than just adding a single rooted.
1036 JS::Rooted
<JSObject
*> scope(cx
, scopeArg
);
1037 if (js::IsWrapper(scope
)) {
1038 scope
= js::CheckedUnwrap(scope
, /* stopAtOuter = */ false);
1041 ac
.emplace(cx
, scope
);
1044 bool tookOwnership
= false;
1045 MOZ_ASSERT(js::IsObjectInContextCompartment(scope
, cx
));
1046 obj
= value
->WrapObject(cx
, &tookOwnership
);
1047 MOZ_ASSERT_IF(obj
, tookOwnership
);
1048 if (tookOwnership
) {
1057 // We can end up here in all sorts of compartments, per above. Make
1058 // sure to JS_WrapValue!
1059 rval
.set(JS::ObjectValue(*obj
));
1060 return JS_WrapValue(cx
, rval
);
1063 // Helper for smart pointers (nsAutoPtr/nsRefPtr/nsCOMPtr).
1064 template <template <typename
> class SmartPtr
, typename T
>
1066 WrapNewBindingNonWrapperCachedObject(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1067 const SmartPtr
<T
>& value
,
1068 JS::MutableHandle
<JS::Value
> rval
)
1070 return WrapNewBindingNonWrapperCachedObject(cx
, scope
, value
.get(), rval
);
1073 // Only set allowNativeWrapper to false if you really know you need it, if in
1074 // doubt use true. Setting it to false disables security wrappers.
1076 NativeInterface2JSObjectAndThrowIfFailed(JSContext
* aCx
,
1077 JS::Handle
<JSObject
*> aScope
,
1078 JS::MutableHandle
<JS::Value
> aRetval
,
1079 xpcObjectHelper
& aHelper
,
1081 bool aAllowNativeWrapper
);
1084 * A method to handle new-binding wrap failure, by possibly falling back to
1085 * wrapping as a non-new-binding object.
1088 MOZ_ALWAYS_INLINE
bool
1089 HandleNewBindingWrappingFailure(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1090 T
* value
, JS::MutableHandle
<JS::Value
> rval
)
1092 if (JS_IsExceptionPending(cx
)) {
1096 qsObjectHelper
helper(value
, GetWrapperCache(value
));
1097 return NativeInterface2JSObjectAndThrowIfFailed(cx
, scope
, rval
,
1098 helper
, nullptr, true);
1101 // Helper for calling HandleNewBindingWrappingFailure with smart pointers
1102 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
1105 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
1106 struct HandleNewBindingWrappingFailureHelper
1108 static inline bool Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1109 const T
& value
, JS::MutableHandle
<JS::Value
> rval
)
1111 return HandleNewBindingWrappingFailure(cx
, scope
, value
.get(), rval
);
1116 struct HandleNewBindingWrappingFailureHelper
<T
, false>
1118 static inline bool Wrap(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
& value
,
1119 JS::MutableHandle
<JS::Value
> rval
)
1121 return HandleNewBindingWrappingFailure(cx
, scope
, &value
, rval
);
1127 HandleNewBindingWrappingFailure(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1128 T
& value
, JS::MutableHandle
<JS::Value
> rval
)
1130 return HandleNewBindingWrappingFailureHelper
<T
>::Wrap(cx
, scope
, value
, rval
);
1133 template<bool Fatal
>
1135 EnumValueNotFound(JSContext
* cx
, JSString
* str
, const char* type
,
1136 const char* sourceDescription
)
1143 EnumValueNotFound
<false>(JSContext
* cx
, JSString
* str
, const char* type
,
1144 const char* sourceDescription
)
1146 // TODO: Log a warning to the console.
1152 EnumValueNotFound
<true>(JSContext
* cx
, JSString
* str
, const char* type
,
1153 const char* sourceDescription
)
1155 JSAutoByteString
deflated(cx
, str
);
1159 return ThrowErrorMessage(cx
, MSG_INVALID_ENUM_VALUE
, sourceDescription
,
1160 deflated
.ptr(), type
);
1163 template<typename CharT
>
1165 FindEnumStringIndexImpl(const CharT
* chars
, size_t length
, const EnumEntry
* values
)
1168 for (const EnumEntry
* value
= values
; value
->value
; ++value
, ++i
) {
1169 if (length
!= value
->length
) {
1174 const char* val
= value
->value
;
1175 for (size_t j
= 0; j
!= length
; ++j
) {
1176 if (unsigned(val
[j
]) != unsigned(chars
[j
])) {
1190 template<bool InvalidValueFatal
>
1192 FindEnumStringIndex(JSContext
* cx
, JS::Handle
<JS::Value
> v
, const EnumEntry
* values
,
1193 const char* type
, const char* sourceDescription
, bool* ok
)
1195 // JS_StringEqualsAscii is slow as molasses, so don't use it here.
1196 JSString
* str
= JS::ToString(cx
, v
);
1205 JS::AutoCheckCannotGC nogc
;
1206 if (js::StringHasLatin1Chars(str
)) {
1207 const JS::Latin1Char
* chars
= JS_GetLatin1StringCharsAndLength(cx
, nogc
, str
,
1213 index
= FindEnumStringIndexImpl(chars
, length
, values
);
1215 const char16_t
* chars
= JS_GetTwoByteStringCharsAndLength(cx
, nogc
, str
,
1221 index
= FindEnumStringIndexImpl(chars
, length
, values
);
1229 *ok
= EnumValueNotFound
<InvalidValueFatal
>(cx
, str
, type
, sourceDescription
);
1233 inline nsWrapperCache
*
1234 GetWrapperCache(const ParentObject
& aParentObject
)
1236 return aParentObject
.mWrapperCache
;
1241 GetParentPointer(T
* aObject
)
1247 GetParentPointer(const ParentObject
& aObject
)
1249 return aObject
.mObject
;
1252 template <typename T
>
1254 GetUseXBLScope(T
* aParentObject
)
1260 GetUseXBLScope(const ParentObject
& aParentObject
)
1262 return aParentObject
.mUseXBLScope
;
1267 ClearWrapper(T
* p
, nsWrapperCache
* cache
)
1269 cache
->ClearWrapper();
1274 ClearWrapper(T
* p
, void*)
1276 nsWrapperCache
* cache
;
1277 CallQueryInterface(p
, &cache
);
1278 ClearWrapper(p
, cache
);
1283 UpdateWrapper(T
* p
, nsWrapperCache
* cache
, JSObject
* obj
, const JSObject
* old
)
1285 JS::AutoAssertGCCallback
inCallback(obj
);
1286 cache
->UpdateWrapper(obj
, old
);
1291 UpdateWrapper(T
* p
, void*, JSObject
* obj
, const JSObject
* old
)
1293 JS::AutoAssertGCCallback
inCallback(obj
);
1294 nsWrapperCache
* cache
;
1295 CallQueryInterface(p
, &cache
);
1296 UpdateWrapper(p
, cache
, obj
, old
);
1299 // Attempt to preserve the wrapper, if any, for a Paris DOM bindings object.
1300 // Return true if we successfully preserved the wrapper, or there is no wrapper
1301 // to preserve. In the latter case we don't need to preserve the wrapper, because
1302 // the object can only be obtained by JS once, or they cannot be meaningfully
1303 // owned from the native side.
1305 // This operation will return false only for non-nsISupports cycle-collected
1306 // objects, because we cannot determine if they are wrappercached or not.
1308 TryPreserveWrapper(JSObject
* obj
);
1310 // Can only be called with a DOM JSClass.
1312 InstanceClassHasProtoAtDepth(const js::Class
* clasp
,
1313 uint32_t protoID
, uint32_t depth
);
1315 // Only set allowNativeWrapper to false if you really know you need it, if in
1316 // doubt use true. Setting it to false disables security wrappers.
1318 XPCOMObjectToJsval(JSContext
* cx
, JS::Handle
<JSObject
*> scope
,
1319 xpcObjectHelper
& helper
, const nsIID
* iid
,
1320 bool allowNativeWrapper
, JS::MutableHandle
<JS::Value
> rval
);
1322 // Special-cased wrapping for variants
1324 VariantToJsval(JSContext
* aCx
, nsIVariant
* aVariant
,
1325 JS::MutableHandle
<JS::Value
> aRetval
);
1327 // Wrap an object "p" which is not using WebIDL bindings yet. This _will_
1328 // actually work on WebIDL binding objects that are wrappercached, but will be
1329 // much slower than GetOrCreateDOMReflector. "cache" must either be null or be
1330 // the nsWrapperCache for "p".
1333 WrapObject(JSContext
* cx
, T
* p
, nsWrapperCache
* cache
, const nsIID
* iid
,
1334 JS::MutableHandle
<JS::Value
> rval
)
1336 if (xpc_FastGetCachedWrapper(cx
, cache
, rval
))
1338 qsObjectHelper
helper(p
, cache
);
1339 JS::Rooted
<JSObject
*> scope(cx
, JS::CurrentGlobalOrNull(cx
));
1340 return XPCOMObjectToJsval(cx
, scope
, helper
, iid
, true, rval
);
1343 // A specialization of the above for nsIVariant, because that needs to
1344 // do something different.
1347 WrapObject
<nsIVariant
>(JSContext
* cx
, nsIVariant
* p
,
1348 nsWrapperCache
* cache
, const nsIID
* iid
,
1349 JS::MutableHandle
<JS::Value
> rval
)
1352 MOZ_ASSERT(iid
->Equals(NS_GET_IID(nsIVariant
)));
1353 return VariantToJsval(cx
, p
, rval
);
1356 // Wrap an object "p" which is not using WebIDL bindings yet. Just like the
1357 // variant that takes an nsWrapperCache above, but will try to auto-derive the
1358 // nsWrapperCache* from "p".
1361 WrapObject(JSContext
* cx
, T
* p
, const nsIID
* iid
,
1362 JS::MutableHandle
<JS::Value
> rval
)
1364 return WrapObject(cx
, p
, GetWrapperCache(p
), iid
, rval
);
1367 // Just like the WrapObject above, but without requiring you to pick which
1368 // interface you're wrapping as. This should only be used for objects that have
1369 // classinfo, for which it doesn't matter what IID is used to wrap.
1372 WrapObject(JSContext
* cx
, T
* p
, JS::MutableHandle
<JS::Value
> rval
)
1374 return WrapObject(cx
, p
, nullptr, rval
);
1377 // Helper to make it possible to wrap directly out of an nsCOMPtr
1380 WrapObject(JSContext
* cx
, const nsCOMPtr
<T
>& p
,
1381 const nsIID
* iid
, JS::MutableHandle
<JS::Value
> rval
)
1383 return WrapObject(cx
, p
.get(), iid
, rval
);
1386 // Helper to make it possible to wrap directly out of an nsCOMPtr
1389 WrapObject(JSContext
* cx
, const nsCOMPtr
<T
>& p
,
1390 JS::MutableHandle
<JS::Value
> rval
)
1392 return WrapObject(cx
, p
, nullptr, rval
);
1395 // Helper to make it possible to wrap directly out of an nsRefPtr
1398 WrapObject(JSContext
* cx
, const nsRefPtr
<T
>& p
,
1399 const nsIID
* iid
, JS::MutableHandle
<JS::Value
> rval
)
1401 return WrapObject(cx
, p
.get(), iid
, rval
);
1404 // Helper to make it possible to wrap directly out of an nsRefPtr
1407 WrapObject(JSContext
* cx
, const nsRefPtr
<T
>& p
,
1408 JS::MutableHandle
<JS::Value
> rval
)
1410 return WrapObject(cx
, p
, nullptr, rval
);
1413 // Specialization to make it easy to use WrapObject in codegen.
1416 WrapObject
<JSObject
>(JSContext
* cx
, JSObject
* p
,
1417 JS::MutableHandle
<JS::Value
> rval
)
1419 rval
.set(JS::ObjectOrNullValue(p
));
1424 WrapObject(JSContext
* cx
, JSObject
& p
, JS::MutableHandle
<JS::Value
> rval
)
1426 rval
.set(JS::ObjectValue(p
));
1430 // Given an object "p" that inherits from nsISupports, wrap it and return the
1431 // result. Null is returned on wrapping failure. This is somewhat similar to
1432 // WrapObject() above, but does NOT allow Xrays around the result, since we
1433 // don't want those for our parent object.
1434 template<typename T
>
1435 static inline JSObject
*
1436 WrapNativeISupportsParent(JSContext
* cx
, T
* p
, nsWrapperCache
* cache
)
1438 qsObjectHelper
helper(ToSupports(p
), cache
);
1439 JS::Rooted
<JSObject
*> scope(cx
, JS::CurrentGlobalOrNull(cx
));
1440 JS::Rooted
<JS::Value
> v(cx
);
1441 return XPCOMObjectToJsval(cx
, scope
, helper
, nullptr, false, &v
) ?
1442 v
.toObjectOrNull() :
1447 // Fallback for when our parent is not a WebIDL binding object.
1448 template<typename T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
1449 struct WrapNativeParentFallback
1451 static inline JSObject
* Wrap(JSContext
* cx
, T
* parent
, nsWrapperCache
* cache
)
1457 // Fallback for when our parent is not a WebIDL binding object but _is_ an
1458 // nsISupports object.
1459 template<typename T
>
1460 struct WrapNativeParentFallback
<T
, true >
1462 static inline JSObject
* Wrap(JSContext
* cx
, T
* parent
, nsWrapperCache
* cache
)
1464 return WrapNativeISupportsParent(cx
, parent
, cache
);
1468 // Wrapping of our native parent, for cases when it's a WebIDL object (though
1469 // possibly preffed off).
1470 template<typename T
, bool hasWrapObject
=HasWrapObject
<T
>::Value
>
1471 struct WrapNativeParentHelper
1473 static inline JSObject
* Wrap(JSContext
* cx
, T
* parent
, nsWrapperCache
* cache
)
1478 if ((obj
= cache
->GetWrapper())) {
1482 // Inline this here while we have non-dom objects in wrapper caches.
1483 if (!CouldBeDOMBinding(parent
)) {
1484 obj
= WrapNativeParentFallback
<T
>::Wrap(cx
, parent
, cache
);
1486 obj
= parent
->WrapObject(cx
);
1493 // Wrapping of our native parent, for cases when it's not a WebIDL object. In
1494 // this case it must be nsISupports.
1495 template<typename T
>
1496 struct WrapNativeParentHelper
<T
, false >
1498 static inline JSObject
* Wrap(JSContext
* cx
, T
* parent
, nsWrapperCache
* cache
)
1501 if (cache
&& (obj
= cache
->GetWrapper())) {
1503 NS_ASSERTION(WrapNativeISupportsParent(cx
, parent
, cache
) == obj
,
1504 "Unexpected object in nsWrapperCache");
1509 return WrapNativeISupportsParent(cx
, parent
, cache
);
1513 // Wrapping of our native parent.
1514 template<typename T
>
1515 static inline JSObject
*
1516 WrapNativeParent(JSContext
* cx
, T
* p
, nsWrapperCache
* cache
,
1517 bool useXBLScope
= false)
1520 return JS::CurrentGlobalOrNull(cx
);
1523 JSObject
* parent
= WrapNativeParentHelper
<T
>::Wrap(cx
, p
, cache
);
1528 // If useXBLScope is true, it means that the canonical reflector for this
1529 // native object should live in the content XBL scope. Note that we never put
1530 // anonymous content inside an add-on scope.
1531 if (xpc::IsInContentXBLScope(parent
)) {
1534 JS::Rooted
<JSObject
*> rootedParent(cx
, parent
);
1535 JS::Rooted
<JSObject
*> xblScope(cx
, xpc::GetXBLScope(cx
, rootedParent
));
1536 NS_ENSURE_TRUE(xblScope
, nullptr);
1537 JSAutoCompartment
ac(cx
, xblScope
);
1538 if (NS_WARN_IF(!JS_WrapObject(cx
, &rootedParent
))) {
1542 return rootedParent
;
1545 // Wrapping of our native parent, when we don't want to explicitly pass in
1546 // things like the nsWrapperCache for it.
1547 template<typename T
>
1548 static inline JSObject
*
1549 WrapNativeParent(JSContext
* cx
, const T
& p
)
1551 return WrapNativeParent(cx
, GetParentPointer(p
), GetWrapperCache(p
), GetUseXBLScope(p
));
1554 HAS_MEMBER(GetParentObject
)
1556 template<typename T
, bool WrapperCached
=HasGetParentObjectMember
<T
>::Value
>
1557 struct GetParentObject
1559 static JSObject
* Get(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
1561 MOZ_ASSERT(js::IsObjectInContextCompartment(obj
, cx
));
1562 T
* native
= UnwrapDOMObject
<T
>(obj
);
1563 JSObject
* wrappedParent
= WrapNativeParent(cx
, native
->GetParentObject());
1564 return wrappedParent
? js::GetGlobalForObjectCrossCompartment(wrappedParent
) : nullptr;
1568 template<typename T
>
1569 struct GetParentObject
<T
, false>
1571 static JSObject
* Get(JSContext
* cx
, JS::Handle
<JSObject
*> obj
)
1579 JSObject
* GetJSObjectFromCallback(CallbackObject
* callback
)
1581 return callback
->Callback();
1585 JSObject
* GetJSObjectFromCallback(void* noncallback
)
1590 template<typename T
>
1591 static inline JSObject
*
1592 WrapCallThisObject(JSContext
* cx
, const T
& p
)
1594 // Callbacks are nsISupports, so WrapNativeParent will just happily wrap them
1595 // up as an nsISupports XPCWrappedNative... which is not at all what we want.
1596 // So we need to special-case them.
1597 JS::Rooted
<JSObject
*> obj(cx
, GetJSObjectFromCallback(p
));
1599 // WrapNativeParent is a bit of a Swiss army knife that will
1600 // wrap anything for us.
1601 obj
= WrapNativeParent(cx
, p
);
1607 // But all that won't necessarily put things in the compartment of cx.
1608 if (!JS_WrapObject(cx
, &obj
)) {
1616 * This specialized function simply wraps a JS::Rooted<> since
1617 * WrapNativeParent() is not applicable for JS objects.
1621 WrapCallThisObject
<JS::Rooted
<JSObject
*>>(JSContext
* cx
,
1622 const JS::Rooted
<JSObject
*>& p
)
1624 JS::Rooted
<JSObject
*> obj(cx
, p
);
1626 if (!JS_WrapObject(cx
, &obj
)) {
1633 // Helper for calling GetOrCreateDOMReflector with smart pointers
1634 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
1635 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
1636 struct GetOrCreateDOMReflectorHelper
1638 static inline bool GetOrCreate(JSContext
* cx
, const T
& value
,
1639 JS::MutableHandle
<JS::Value
> rval
)
1641 return GetOrCreateDOMReflector(cx
, value
.get(), rval
);
1646 struct GetOrCreateDOMReflectorHelper
<T
, false>
1648 static inline bool GetOrCreate(JSContext
* cx
, T
& value
,
1649 JS::MutableHandle
<JS::Value
> rval
)
1651 return GetOrCreateDOMReflector(cx
, &value
, rval
);
1657 GetOrCreateDOMReflector(JSContext
* cx
, T
& value
,
1658 JS::MutableHandle
<JS::Value
> rval
)
1660 return GetOrCreateDOMReflectorHelper
<T
>::GetOrCreate(cx
, value
, rval
);
1663 // We need this version of GetOrCreateDOMReflector for codegen, so it'll have
1664 // the same signature as WrapNewBindingNonWrapperCachedObject and
1665 // WrapNewBindingNonWrapperCachedOwnedObject, which still need the scope.
1668 GetOrCreateDOMReflector(JSContext
* cx
, JS::Handle
<JSObject
*> scope
, T
& value
,
1669 JS::MutableHandle
<JS::Value
> rval
)
1671 return GetOrCreateDOMReflector(cx
, value
, rval
);
1674 // Helper for calling GetOrCreateDOMReflectorNoWrap with smart pointers
1675 // (nsAutoPtr/nsRefPtr/nsCOMPtr) or references.
1676 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
1677 struct GetOrCreateDOMReflectorNoWrapHelper
1679 static inline bool GetOrCreate(JSContext
* cx
, const T
& value
,
1680 JS::MutableHandle
<JS::Value
> rval
)
1682 return GetOrCreateDOMReflectorNoWrap(cx
, value
.get(), rval
);
1687 struct GetOrCreateDOMReflectorNoWrapHelper
<T
, false>
1689 static inline bool GetOrCreate(JSContext
* cx
, T
& value
,
1690 JS::MutableHandle
<JS::Value
> rval
)
1692 return GetOrCreateDOMReflectorNoWrap(cx
, &value
, rval
);
1698 GetOrCreateDOMReflectorNoWrap(JSContext
* cx
, T
& value
,
1699 JS::MutableHandle
<JS::Value
> rval
)
1702 GetOrCreateDOMReflectorNoWrapHelper
<T
>::GetOrCreate(cx
, value
, rval
);
1707 GetCallbackFromCallbackObject(T
* aObj
)
1709 return aObj
->Callback();
1712 // Helper for getting the callback JSObject* of a smart ptr around a
1713 // CallbackObject or a reference to a CallbackObject or something like
1715 template <class T
, bool isSmartPtr
=HasgetMember
<T
>::Value
>
1716 struct GetCallbackFromCallbackObjectHelper
1718 static inline JSObject
* Get(const T
& aObj
)
1720 return GetCallbackFromCallbackObject(aObj
.get());
1725 struct GetCallbackFromCallbackObjectHelper
<T
, false>
1727 static inline JSObject
* Get(T
& aObj
)
1729 return GetCallbackFromCallbackObject(&aObj
);
1735 GetCallbackFromCallbackObject(T
& aObj
)
1737 return GetCallbackFromCallbackObjectHelper
<T
>::Get(aObj
);
1741 InternJSString(JSContext
* cx
, jsid
& id
, const char* chars
)
1743 if (JSString
*str
= ::JS_InternString(cx
, chars
)) {
1744 id
= INTERNED_STRING_TO_JSID(cx
, str
);
1750 // Spec needs a name property
1751 template <typename Spec
>
1753 InitIds(JSContext
* cx
, const Prefable
<Spec
>* prefableSpecs
, jsid
* ids
)
1755 MOZ_ASSERT(prefableSpecs
);
1756 MOZ_ASSERT(prefableSpecs
->specs
);
1758 // We ignore whether the set of ids is enabled and just intern all the IDs,
1759 // because this is only done once per application runtime.
1760 Spec
* spec
= prefableSpecs
->specs
;
1762 if (!JS::PropertySpecNameToPermanentId(cx
, spec
->name
, ids
)) {
1765 } while (++ids
, (++spec
)->name
);
1767 // We ran out of ids for that pref. Put a JSID_VOID in on the id
1768 // corresponding to the list terminator for the pref.
1771 } while ((++prefableSpecs
)->specs
);
1777 QueryInterface(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
1783 static_assert(IsBaseOf
<nsISupports
, T
>::value
,
1784 "QueryInterface can't work without an nsISupports.");
1785 static bool Enabled(JSContext
* aCx
, JSObject
* aGlobal
)
1787 return NS_IsMainThread() && IsChromeOrXBL(aCx
, aGlobal
);
1792 GetInterfaceImpl(JSContext
* aCx
, nsIInterfaceRequestor
* aRequestor
,
1793 nsWrapperCache
* aCache
, nsIJSID
* aIID
,
1794 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aError
);
1798 GetInterface(JSContext
* aCx
, T
* aThis
, nsIJSID
* aIID
,
1799 JS::MutableHandle
<JS::Value
> aRetval
, ErrorResult
& aError
)
1801 GetInterfaceImpl(aCx
, aThis
, aThis
, aIID
, aRetval
, aError
);
1805 UnforgeableValueOf(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
1808 ThrowingConstructor(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
1811 ThrowConstructorWithoutNew(JSContext
* cx
, const char* name
);
1814 GetPropertyOnPrototype(JSContext
* cx
, JS::Handle
<JSObject
*> proxy
,
1815 JS::Handle
<jsid
> id
, bool* found
,
1816 JS::MutableHandle
<JS::Value
> vp
);
1820 HasPropertyOnPrototype(JSContext
* cx
, JS::Handle
<JSObject
*> proxy
,
1821 JS::Handle
<jsid
> id
, bool* has
);
1824 // Append the property names in "names" to "props". If
1825 // shadowPrototypeProperties is false then skip properties that are also
1826 // present on the proto chain of proxy. If shadowPrototypeProperties is true,
1827 // then the "proxy" argument is ignored.
1829 AppendNamedPropertyIds(JSContext
* cx
, JS::Handle
<JSObject
*> proxy
,
1830 nsTArray
<nsString
>& names
,
1831 bool shadowPrototypeProperties
, JS::AutoIdVector
& props
);
1833 namespace binding_detail
{
1835 // A struct that has the same layout as an nsString but much faster
1836 // constructor and destructor behavior. FakeString uses inline storage
1837 // for small strings and a nsStringBuffer for longer strings.
1840 mFlags(nsString::F_TERMINATED
)
1845 if (mFlags
& nsString::F_SHARED
) {
1846 nsStringBuffer::FromData(mData
)->Release();
1850 void Rebind(const nsString::char_type
* aData
, nsString::size_type aLength
) {
1851 MOZ_ASSERT(mFlags
== nsString::F_TERMINATED
);
1852 mData
= const_cast<nsString::char_type
*>(aData
);
1857 MOZ_ASSERT(mFlags
== nsString::F_TERMINATED
);
1858 mData
= nsString::char_traits::sEmptyBuffer
;
1862 void SetIsVoid(bool aValue
) {
1864 "We don't support SetIsVoid(false) on FakeString!");
1866 mFlags
|= nsString::F_VOIDED
;
1869 const nsString::char_type
* Data() const
1874 nsString::char_type
* BeginWriting()
1879 nsString::size_type
Length() const
1884 // Reserve space to write aLength chars, not including null-terminator.
1885 bool SetLength(nsString::size_type aLength
, mozilla::fallible_t
const&) {
1886 // Use mInlineStorage for small strings.
1887 if (aLength
< sInlineCapacity
) {
1888 SetData(mInlineStorage
);
1890 nsStringBuffer
*buf
= nsStringBuffer::Alloc((aLength
+ 1) * sizeof(nsString::char_type
)).take();
1891 if (MOZ_UNLIKELY(!buf
)) {
1895 SetData(static_cast<nsString::char_type
*>(buf
->Data()));
1896 mFlags
= nsString::F_SHARED
| nsString::F_TERMINATED
;
1899 mData
[mLength
] = char16_t(0);
1903 // If this ever changes, change the corresponding code in the
1904 // Optional<nsAString> specialization as well.
1905 const nsAString
* ToAStringPtr() const {
1906 return reinterpret_cast<const nsString
*>(this);
1909 nsAString
* ToAStringPtr() {
1910 return reinterpret_cast<nsString
*>(this);
1913 operator const nsAString
& () const {
1914 return *reinterpret_cast<const nsString
*>(this);
1918 nsString::char_type
* mData
;
1919 nsString::size_type mLength
;
1922 static const size_t sInlineCapacity
= 64;
1923 nsString::char_type mInlineStorage
[sInlineCapacity
];
1925 FakeString(const FakeString
& other
) = delete;
1926 void operator=(const FakeString
& other
) = delete;
1928 void SetData(nsString::char_type
* aData
) {
1929 MOZ_ASSERT(mFlags
== nsString::F_TERMINATED
);
1930 mData
= const_cast<nsString::char_type
*>(aData
);
1933 // A class to use for our static asserts to ensure our object layout
1934 // matches that of nsString.
1935 class StringAsserter
;
1936 friend class StringAsserter
;
1938 class StringAsserter
: public nsString
{
1940 static void StaticAsserts() {
1941 static_assert(offsetof(FakeString
, mInlineStorage
) ==
1943 "FakeString should include all nsString members");
1944 static_assert(offsetof(FakeString
, mData
) ==
1945 offsetof(StringAsserter
, mData
),
1946 "Offset of mData should match");
1947 static_assert(offsetof(FakeString
, mLength
) ==
1948 offsetof(StringAsserter
, mLength
),
1949 "Offset of mLength should match");
1950 static_assert(offsetof(FakeString
, mFlags
) ==
1951 offsetof(StringAsserter
, mFlags
),
1952 "Offset of mFlags should match");
1957 } // namespace binding_detail
1959 enum StringificationBehavior
{
1965 template<typename T
>
1967 ConvertJSValueToString(JSContext
* cx
, JS::Handle
<JS::Value
> v
,
1968 StringificationBehavior nullBehavior
,
1969 StringificationBehavior undefinedBehavior
,
1976 StringificationBehavior behavior
;
1978 behavior
= nullBehavior
;
1979 } else if (v
.isUndefined()) {
1980 behavior
= undefinedBehavior
;
1982 behavior
= eStringify
;
1985 if (behavior
!= eStringify
) {
1986 if (behavior
== eEmpty
) {
1989 result
.SetIsVoid(true);
1994 s
= JS::ToString(cx
, v
);
2000 return AssignJSString(cx
, result
, s
);
2004 NormalizeUSVString(JSContext
* aCx
, nsAString
& aString
);
2007 NormalizeUSVString(JSContext
* aCx
, binding_detail::FakeString
& aString
);
2009 template<typename T
>
2011 ConvertIdToString(JSContext
* cx
, JS::HandleId id
, T
& result
, bool& isSymbol
)
2013 if (MOZ_LIKELY(JSID_IS_STRING(id
))) {
2014 if (!AssignJSString(cx
, result
, JSID_TO_STRING(id
))) {
2017 } else if (JSID_IS_SYMBOL(id
)) {
2021 JS::RootedValue
nameVal(cx
, js::IdToValue(id
));
2022 if (!ConvertJSValueToString(cx
, nameVal
, eStringify
, eStringify
, result
)) {
2031 ConvertJSValueToByteString(JSContext
* cx
, JS::Handle
<JS::Value
> v
,
2032 bool nullable
, nsACString
& result
);
2034 template<typename T
>
2035 void DoTraceSequence(JSTracer
* trc
, FallibleTArray
<T
>& seq
);
2036 template<typename T
>
2037 void DoTraceSequence(JSTracer
* trc
, InfallibleTArray
<T
>& seq
);
2039 // Class for simple sequence arguments, only used internally by codegen.
2040 namespace binding_detail
{
2042 template<typename T
>
2043 class AutoSequence
: public AutoFallibleTArray
<T
, 16>
2046 AutoSequence() : AutoFallibleTArray
<T
, 16>()
2049 // Allow converting to const sequences as needed
2050 operator const Sequence
<T
>&() const {
2051 return *reinterpret_cast<const Sequence
<T
>*>(this);
2055 } // namespace binding_detail
2057 // Class used to trace sequences, with specializations for various
2059 template<typename T
,
2060 bool isDictionary
=IsBaseOf
<DictionaryBase
, T
>::value
,
2061 bool isTypedArray
=IsBaseOf
<AllTypedArraysBase
, T
>::value
,
2062 bool isOwningUnion
=IsBaseOf
<AllOwningUnionBase
, T
>::value
>
2063 class SequenceTracer
2065 explicit SequenceTracer() = delete; // Should never be instantiated
2068 // sequence<object> or sequence<object?>
2070 class SequenceTracer
<JSObject
*, false, false, false>
2072 explicit SequenceTracer() = delete; // Should never be instantiated
2075 static void TraceSequence(JSTracer
* trc
, JSObject
** objp
, JSObject
** end
) {
2076 for (; objp
!= end
; ++objp
) {
2077 JS_CallUnbarrieredObjectTracer(trc
, objp
, "sequence<object>");
2084 class SequenceTracer
<JS::Value
, false, false, false>
2086 explicit SequenceTracer() = delete; // Should never be instantiated
2089 static void TraceSequence(JSTracer
* trc
, JS::Value
* valp
, JS::Value
* end
) {
2090 for (; valp
!= end
; ++valp
) {
2091 JS_CallUnbarrieredValueTracer(trc
, valp
, "sequence<any>");
2096 // sequence<sequence<T>>
2097 template<typename T
>
2098 class SequenceTracer
<Sequence
<T
>, false, false, false>
2100 explicit SequenceTracer() = delete; // Should never be instantiated
2103 static void TraceSequence(JSTracer
* trc
, Sequence
<T
>* seqp
, Sequence
<T
>* end
) {
2104 for (; seqp
!= end
; ++seqp
) {
2105 DoTraceSequence(trc
, *seqp
);
2110 // sequence<sequence<T>> as return value
2111 template<typename T
>
2112 class SequenceTracer
<nsTArray
<T
>, false, false, false>
2114 explicit SequenceTracer() = delete; // Should never be instantiated
2117 static void TraceSequence(JSTracer
* trc
, nsTArray
<T
>* seqp
, nsTArray
<T
>* end
) {
2118 for (; seqp
!= end
; ++seqp
) {
2119 DoTraceSequence(trc
, *seqp
);
2124 // sequence<someDictionary>
2125 template<typename T
>
2126 class SequenceTracer
<T
, true, false, false>
2128 explicit SequenceTracer() = delete; // Should never be instantiated
2131 static void TraceSequence(JSTracer
* trc
, T
* dictp
, T
* end
) {
2132 for (; dictp
!= end
; ++dictp
) {
2133 dictp
->TraceDictionary(trc
);
2138 // sequence<SomeTypedArray>
2139 template<typename T
>
2140 class SequenceTracer
<T
, false, true, false>
2142 explicit SequenceTracer() = delete; // Should never be instantiated
2145 static void TraceSequence(JSTracer
* trc
, T
* arrayp
, T
* end
) {
2146 for (; arrayp
!= end
; ++arrayp
) {
2147 arrayp
->TraceSelf(trc
);
2152 // sequence<SomeOwningUnion>
2153 template<typename T
>
2154 class SequenceTracer
<T
, false, false, true>
2156 explicit SequenceTracer() = delete; // Should never be instantiated
2159 static void TraceSequence(JSTracer
* trc
, T
* arrayp
, T
* end
) {
2160 for (; arrayp
!= end
; ++arrayp
) {
2161 arrayp
->TraceUnion(trc
);
2166 // sequence<T?> with T? being a Nullable<T>
2167 template<typename T
>
2168 class SequenceTracer
<Nullable
<T
>, false, false, false>
2170 explicit SequenceTracer() = delete; // Should never be instantiated
2173 static void TraceSequence(JSTracer
* trc
, Nullable
<T
>* seqp
,
2175 for (; seqp
!= end
; ++seqp
) {
2176 if (!seqp
->IsNull()) {
2177 // Pretend like we actually have a length-one sequence here so
2178 // we can do template instantiation correctly for T.
2179 T
& val
= seqp
->Value();
2181 SequenceTracer
<T
>::TraceSequence(trc
, ptr
, ptr
+1);
2187 // XXXbz It's not clear whether it's better to add a pldhash dependency here
2188 // (for PLDHashOperator) or add a BindingUtils.h dependency (for
2189 // SequenceTracer) to MozMap.h...
2190 template<typename T
>
2191 static PLDHashOperator
2192 TraceMozMapValue(T
* aValue
, void* aClosure
)
2194 JSTracer
* trc
= static_cast<JSTracer
*>(aClosure
);
2195 // Act like it's a one-element sequence to leverage all that infrastructure.
2196 SequenceTracer
<T
>::TraceSequence(trc
, aValue
, aValue
+ 1);
2197 return PL_DHASH_NEXT
;
2200 template<typename T
>
2201 void TraceMozMap(JSTracer
* trc
, MozMap
<T
>& map
)
2203 map
.EnumerateValues(TraceMozMapValue
<T
>, trc
);
2207 template<typename T
>
2208 class SequenceTracer
<MozMap
<T
>, false, false, false>
2210 explicit SequenceTracer() = delete; // Should never be instantiated
2213 static void TraceSequence(JSTracer
* trc
, MozMap
<T
>* seqp
, MozMap
<T
>* end
) {
2214 for (; seqp
!= end
; ++seqp
) {
2215 seqp
->EnumerateValues(TraceMozMapValue
<T
>, trc
);
2220 template<typename T
>
2221 void DoTraceSequence(JSTracer
* trc
, FallibleTArray
<T
>& seq
)
2223 SequenceTracer
<T
>::TraceSequence(trc
, seq
.Elements(),
2224 seq
.Elements() + seq
.Length());
2227 template<typename T
>
2228 void DoTraceSequence(JSTracer
* trc
, InfallibleTArray
<T
>& seq
)
2230 SequenceTracer
<T
>::TraceSequence(trc
, seq
.Elements(),
2231 seq
.Elements() + seq
.Length());
2234 // Rooter class for sequences; this is what we mostly use in the codegen
2235 template<typename T
>
2236 class MOZ_STACK_CLASS SequenceRooter
: private JS::CustomAutoRooter
2239 SequenceRooter(JSContext
*aCx
, FallibleTArray
<T
>* aSequence
2240 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
2241 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
2242 mFallibleArray(aSequence
),
2243 mSequenceType(eFallibleArray
)
2247 SequenceRooter(JSContext
*aCx
, InfallibleTArray
<T
>* aSequence
2248 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
2249 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
2250 mInfallibleArray(aSequence
),
2251 mSequenceType(eInfallibleArray
)
2255 SequenceRooter(JSContext
*aCx
, Nullable
<nsTArray
<T
> >* aSequence
2256 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
2257 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
2258 mNullableArray(aSequence
),
2259 mSequenceType(eNullableArray
)
2270 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
2272 if (mSequenceType
== eFallibleArray
) {
2273 DoTraceSequence(trc
, *mFallibleArray
);
2274 } else if (mSequenceType
== eInfallibleArray
) {
2275 DoTraceSequence(trc
, *mInfallibleArray
);
2277 MOZ_ASSERT(mSequenceType
== eNullableArray
);
2278 if (!mNullableArray
->IsNull()) {
2279 DoTraceSequence(trc
, mNullableArray
->Value());
2285 InfallibleTArray
<T
>* mInfallibleArray
;
2286 FallibleTArray
<T
>* mFallibleArray
;
2287 Nullable
<nsTArray
<T
> >* mNullableArray
;
2290 SequenceType mSequenceType
;
2293 // Rooter class for MozMap; this is what we mostly use in the codegen.
2294 template<typename T
>
2295 class MOZ_STACK_CLASS MozMapRooter
: private JS::CustomAutoRooter
2298 MozMapRooter(JSContext
*aCx
, MozMap
<T
>* aMozMap
2299 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
2300 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
2302 mMozMapType(eMozMap
)
2306 MozMapRooter(JSContext
*aCx
, Nullable
<MozMap
<T
>>* aMozMap
2307 MOZ_GUARD_OBJECT_NOTIFIER_PARAM
)
2308 : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
),
2309 mNullableMozMap(aMozMap
),
2310 mMozMapType(eNullableMozMap
)
2320 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
2322 if (mMozMapType
== eMozMap
) {
2323 TraceMozMap(trc
, *mMozMap
);
2325 MOZ_ASSERT(mMozMapType
== eNullableMozMap
);
2326 if (!mNullableMozMap
->IsNull()) {
2327 TraceMozMap(trc
, mNullableMozMap
->Value());
2334 Nullable
<MozMap
<T
>>* mNullableMozMap
;
2337 MozMapType mMozMapType
;
2340 template<typename T
>
2341 class MOZ_STACK_CLASS RootedUnion
: public T
,
2342 private JS::CustomAutoRooter
2345 explicit RootedUnion(JSContext
* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM
) :
2347 JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
)
2351 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
2353 this->TraceUnion(trc
);
2357 template<typename T
>
2358 class MOZ_STACK_CLASS NullableRootedUnion
: public Nullable
<T
>,
2359 private JS::CustomAutoRooter
2362 explicit NullableRootedUnion(JSContext
* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM
) :
2364 JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
)
2368 virtual void trace(JSTracer
*trc
) MOZ_OVERRIDE
2370 if (!this->IsNull()) {
2371 this->Value().TraceUnion(trc
);
2377 IdEquals(jsid id
, const char* string
)
2379 return JSID_IS_STRING(id
) &&
2380 JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id
), string
);
2384 AddStringToIDVector(JSContext
* cx
, JS::AutoIdVector
& vector
, const char* name
)
2386 return vector
.growBy(1) &&
2387 InternJSString(cx
, *(vector
[vector
.length() - 1]).address(), name
);
2390 // Implementation of the bits that XrayWrapper needs
2393 * This resolves operations, attributes and constants of the interfaces for obj.
2395 * wrapper is the Xray JS object.
2396 * obj is the target object of the Xray, a binding's instance object or a
2397 * interface or interface prototype object.
2400 XrayResolveOwnProperty(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
2401 JS::Handle
<JSObject
*> obj
,
2402 JS::Handle
<jsid
> id
,
2403 JS::MutableHandle
<JSPropertyDescriptor
> desc
,
2404 bool& cacheOnHolder
);
2407 * Define a property on obj through an Xray wrapper.
2409 * wrapper is the Xray JS object.
2410 * obj is the target object of the Xray, a binding's instance object or a
2411 * interface or interface prototype object.
2412 * defined will be set to true if a property was set as a result of this call.
2415 XrayDefineProperty(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
2416 JS::Handle
<JSObject
*> obj
, JS::Handle
<jsid
> id
,
2417 JS::MutableHandle
<JSPropertyDescriptor
> desc
, bool* defined
);
2420 * Add to props the property keys of all indexed or named properties of obj and
2421 * operations, attributes and constants of the interfaces for obj.
2423 * wrapper is the Xray JS object.
2424 * obj is the target object of the Xray, a binding's instance object or a
2425 * interface or interface prototype object.
2426 * flags are JSITER_* flags.
2429 XrayOwnPropertyKeys(JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
,
2430 JS::Handle
<JSObject
*> obj
,
2431 unsigned flags
, JS::AutoIdVector
& props
);
2434 * Returns the prototype to use for an Xray for a DOM object, wrapped in cx's
2435 * compartment. This always returns the prototype that would be used for a DOM
2436 * object if we ignore any changes that might have been done to the prototype
2437 * chain by JS, the XBL code or plugins.
2439 * cx should be in the Xray's compartment.
2440 * obj is the target object of the Xray, a binding's instance object or an
2441 * interface or interface prototype object.
2444 XrayGetNativeProto(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
2445 JS::MutableHandle
<JSObject
*> protop
)
2447 JS::Rooted
<JSObject
*> global(cx
, js::GetGlobalForObjectCrossCompartment(obj
));
2449 JSAutoCompartment
ac(cx
, global
);
2450 const DOMJSClass
* domClass
= GetDOMClass(obj
);
2452 ProtoHandleGetter protoGetter
= domClass
->mGetProto
;
2454 protop
.set(protoGetter(cx
, global
));
2456 protop
.set(JS_GetObjectPrototype(cx
, global
));
2459 const js::Class
* clasp
= js::GetObjectClass(obj
);
2460 MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp
));
2461 ProtoGetter protoGetter
=
2462 DOMIfaceAndProtoJSClass::FromJSClass(clasp
)->mGetParentProto
;
2463 protop
.set(protoGetter(cx
, global
));
2467 return JS_WrapObject(cx
, protop
);
2470 extern NativePropertyHooks sWorkerNativePropertyHooks
;
2472 // We use one constructor JSNative to represent all DOM interface objects (so
2473 // we can easily detect when we need to wrap them in an Xray wrapper). We store
2474 // the real JSNative in the mNative member of a JSNativeHolder in the
2475 // CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
2476 // specific interface object. We also store the NativeProperties in the
2478 // Note that some interface objects are not yet a JSFunction but a normal
2479 // JSObject with a DOMJSClass, those do not use these slots.
2482 CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT
= 0
2486 Constructor(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
2489 UseDOMXray(JSObject
* obj
)
2491 const js::Class
* clasp
= js::GetObjectClass(obj
);
2492 return IsDOMClass(clasp
) ||
2493 JS_IsNativeFunction(obj
, Constructor
) ||
2494 IsDOMIfaceAndProtoClass(clasp
);
2499 HasConstructor(JSObject
* obj
)
2501 return JS_IsNativeFunction(obj
, Constructor
) ||
2502 js::GetObjectClass(obj
)->construct
;
2506 // Transfer reference in ptr to smartPtr.
2509 Take(nsRefPtr
<T
>& smartPtr
, T
* ptr
)
2511 smartPtr
= dont_AddRef(ptr
);
2514 // Transfer ownership of ptr to smartPtr.
2517 Take(nsAutoPtr
<T
>& smartPtr
, T
* ptr
)
2523 MustInheritFromNonRefcountedDOMObject(NonRefcountedDOMObject
*)
2527 HAS_MEMBER(JSBindingFinalized
)
2529 template<class T
, bool hasCallback
=HasJSBindingFinalizedMember
<T
>::Value
>
2530 struct JSBindingFinalized
2532 static void Finalized(T
* self
)
2538 struct JSBindingFinalized
<T
, true>
2540 static void Finalized(T
* self
)
2542 self
->JSBindingFinalized();
2546 // Helpers for creating a const version of a type.
2547 template<typename T
>
2548 const T
& Constify(T
& arg
)
2553 // Helper for turning (Owning)NonNull<T> into T&
2554 template<typename T
>
2555 T
& NonNullHelper(T
& aArg
)
2560 template<typename T
>
2561 T
& NonNullHelper(NonNull
<T
>& aArg
)
2566 template<typename T
>
2567 const T
& NonNullHelper(const NonNull
<T
>& aArg
)
2572 template<typename T
>
2573 T
& NonNullHelper(OwningNonNull
<T
>& aArg
)
2578 template<typename T
>
2579 const T
& NonNullHelper(const OwningNonNull
<T
>& aArg
)
2585 void NonNullHelper(NonNull
<binding_detail::FakeString
>& aArg
)
2587 // This overload is here to make sure that we never end up applying
2588 // NonNullHelper to a NonNull<binding_detail::FakeString>. If we
2589 // try to, it should fail to compile, since presumably the caller will try to
2590 // use our nonexistent return value.
2594 void NonNullHelper(const NonNull
<binding_detail::FakeString
>& aArg
)
2596 // This overload is here to make sure that we never end up applying
2597 // NonNullHelper to a NonNull<binding_detail::FakeString>. If we
2598 // try to, it should fail to compile, since presumably the caller will try to
2599 // use our nonexistent return value.
2603 void NonNullHelper(binding_detail::FakeString
& aArg
)
2605 // This overload is here to make sure that we never end up applying
2606 // NonNullHelper to a FakeString before we've constified it. If we
2607 // try to, it should fail to compile, since presumably the caller will try to
2608 // use our nonexistent return value.
2612 const nsAString
& NonNullHelper(const binding_detail::FakeString
& aArg
)
2617 // Reparent the wrapper of aObj to whatever its native now thinks its
2618 // parent should be.
2620 ReparentWrapper(JSContext
* aCx
, JS::Handle
<JSObject
*> aObj
);
2623 * Used to implement the hasInstance hook of an interface object.
2625 * instance should not be a security wrapper.
2628 InterfaceHasInstance(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
2629 JS::Handle
<JSObject
*> instance
,
2632 InterfaceHasInstance(JSContext
* cx
, JS::Handle
<JSObject
*> obj
, JS::MutableHandle
<JS::Value
> vp
,
2635 InterfaceHasInstance(JSContext
* cx
, int prototypeID
, int depth
,
2636 JS::Handle
<JSObject
*> instance
,
2639 // Helper for lenient getters/setters to report to console. If this
2640 // returns false, we couldn't even get a global.
2642 ReportLenientThisUnwrappingFailure(JSContext
* cx
, JSObject
* obj
);
2645 GetUnforgeableHolder(JSObject
* aGlobal
, prototypes::ID aId
)
2647 ProtoAndIfaceCache
& protoAndIfaceCache
= *GetProtoAndIfaceCache(aGlobal
);
2648 JSObject
* interfaceProto
= protoAndIfaceCache
.EntrySlotMustExist(aId
);
2649 return &js::GetReservedSlot(interfaceProto
,
2650 DOM_INTERFACE_PROTO_SLOTS_BASE
).toObject();
2653 // Given a JSObject* that represents the chrome side of a JS-implemented WebIDL
2654 // interface, get the nsIGlobalObject corresponding to the content side, if any.
2655 // A false return means an exception was thrown.
2657 GetContentGlobalForJSImplementedObject(JSContext
* cx
, JS::Handle
<JSObject
*> obj
,
2658 nsIGlobalObject
** global
);
2661 ConstructJSImplementation(JSContext
* aCx
, const char* aContractId
,
2662 nsIGlobalObject
* aGlobal
,
2663 JS::MutableHandle
<JSObject
*> aObject
,
2666 already_AddRefed
<nsIGlobalObject
>
2667 ConstructJSImplementation(JSContext
* aCx
, const char* aContractId
,
2668 const GlobalObject
& aGlobal
,
2669 JS::MutableHandle
<JSObject
*> aObject
,
2673 * Convert an nsCString to jsval, returning true on success.
2674 * These functions are intended for ByteString implementations.
2675 * As such, the string is not UTF-8 encoded. Any UTF8 strings passed to these
2676 * methods will be mangled.
2678 bool NonVoidByteStringToJsval(JSContext
*cx
, const nsACString
&str
,
2679 JS::MutableHandle
<JS::Value
> rval
);
2680 inline bool ByteStringToJsval(JSContext
*cx
, const nsACString
&str
,
2681 JS::MutableHandle
<JS::Value
> rval
)
2687 return NonVoidByteStringToJsval(cx
, str
, rval
);
2690 template<class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2691 struct PreserveWrapperHelper
2693 static void PreserveWrapper(T
* aObject
)
2695 aObject
->PreserveWrapper(aObject
, NS_CYCLE_COLLECTION_PARTICIPANT(T
));
2700 struct PreserveWrapperHelper
<T
, true>
2702 static void PreserveWrapper(T
* aObject
)
2704 aObject
->PreserveWrapper(reinterpret_cast<nsISupports
*>(aObject
));
2709 void PreserveWrapper(T
* aObject
)
2711 PreserveWrapperHelper
<T
>::PreserveWrapper(aObject
);
2714 template<class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2715 struct CastingAssertions
2717 static bool ToSupportsIsCorrect(T
*)
2721 static bool ToSupportsIsOnPrimaryInheritanceChain(T
*, nsWrapperCache
*)
2728 struct CastingAssertions
<T
, true>
2730 static bool ToSupportsIsCorrect(T
* aObject
)
2732 return ToSupports(aObject
) == reinterpret_cast<nsISupports
*>(aObject
);
2734 static bool ToSupportsIsOnPrimaryInheritanceChain(T
* aObject
,
2735 nsWrapperCache
* aCache
)
2737 return reinterpret_cast<void*>(aObject
) != aCache
;
2743 ToSupportsIsCorrect(T
* aObject
)
2745 return CastingAssertions
<T
>::ToSupportsIsCorrect(aObject
);
2750 ToSupportsIsOnPrimaryInheritanceChain(T
* aObject
, nsWrapperCache
* aCache
)
2752 return CastingAssertions
<T
>::ToSupportsIsOnPrimaryInheritanceChain(aObject
,
2756 template<class T
, template <typename
> class SmartPtr
,
2757 bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2758 class DeferredFinalizer
2760 typedef nsTArray
<SmartPtr
<T
> > SmartPtrArray
;
2763 AppendDeferredFinalizePointer(void* aData
, void* aObject
)
2765 SmartPtrArray
* pointers
= static_cast<SmartPtrArray
*>(aData
);
2767 pointers
= new SmartPtrArray();
2770 T
* self
= static_cast<T
*>(aObject
);
2772 SmartPtr
<T
>* defer
= pointers
->AppendElement();
2777 DeferredFinalize(uint32_t aSlice
, void* aData
)
2779 MOZ_ASSERT(aSlice
> 0, "nonsensical/useless call with aSlice == 0");
2780 SmartPtrArray
* pointers
= static_cast<SmartPtrArray
*>(aData
);
2781 uint32_t oldLen
= pointers
->Length();
2782 if (oldLen
< aSlice
) {
2785 uint32_t newLen
= oldLen
- aSlice
;
2786 pointers
->RemoveElementsAt(newLen
, aSlice
);
2796 AddForDeferredFinalization(T
* aObject
)
2798 cyclecollector::DeferredFinalize(AppendDeferredFinalizePointer
,
2799 DeferredFinalize
, aObject
);
2803 template<class T
, template <typename
> class SmartPtr
>
2804 class DeferredFinalizer
<T
, SmartPtr
, true>
2808 AddForDeferredFinalization(T
* aObject
)
2810 cyclecollector::DeferredFinalize(reinterpret_cast<nsISupports
*>(aObject
));
2814 template<class T
, template <typename
> class SmartPtr
>
2816 AddForDeferredFinalization(T
* aObject
)
2818 DeferredFinalizer
<T
, SmartPtr
>::AddForDeferredFinalization(aObject
);
2821 // This returns T's CC participant if it participates in CC or null if it
2822 // doesn't. This also returns null for classes that don't inherit from
2823 // nsISupports (QI should be used to get the participant for those).
2824 template<class T
, bool isISupports
=IsBaseOf
<nsISupports
, T
>::value
>
2825 class GetCCParticipant
2827 // Helper for GetCCParticipant for classes that participate in CC.
2829 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2830 GetHelper(int, typename
U::NS_CYCLE_COLLECTION_INNERCLASS
* dummy
=nullptr)
2832 return T::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant();
2834 // Helper for GetCCParticipant for classes that don't participate in CC.
2836 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2843 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2846 // Passing int() here will try to call the GetHelper that takes an int as
2847 // its firt argument. If T doesn't participate in CC then substitution for
2848 // the second argument (with a default value) will fail and because of
2849 // SFINAE the next best match (the variant taking a double) will be called.
2850 return GetHelper
<T
>(int());
2855 class GetCCParticipant
<T
, true>
2858 static MOZ_CONSTEXPR nsCycleCollectionParticipant
*
2866 * Helper function for testing whether the given object comes from a
2870 IsInPrivilegedApp(JSContext
* aCx
, JSObject
* aObj
);
2873 * Helper function for testing whether the given object comes from a
2877 IsInCertifiedApp(JSContext
* aCx
, JSObject
* aObj
);
2880 FinalizeGlobal(JSFreeOp
* aFop
, JSObject
* aObj
);
2883 ResolveGlobal(JSContext
* aCx
, JS::Handle
<JSObject
*> aObj
,
2884 JS::Handle
<jsid
> aId
, bool* aResolvedp
);
2887 EnumerateGlobal(JSContext
* aCx
, JS::Handle
<JSObject
*> aObj
);
2890 struct CreateGlobalOptions
2892 static MOZ_CONSTEXPR_VAR
ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind
=
2893 ProtoAndIfaceCache::NonWindowLike
;
2894 // Intl API is broken and makes JS_InitStandardClasses fail intermittently,
2896 static MOZ_CONSTEXPR_VAR
bool ForceInitStandardClassesToFalse
= true;
2897 static void TraceGlobal(JSTracer
* aTrc
, JSObject
* aObj
)
2899 mozilla::dom::TraceProtoAndIfaceCache(aTrc
, aObj
);
2901 static bool PostCreateGlobal(JSContext
* aCx
, JS::Handle
<JSObject
*> aGlobal
)
2903 MOZ_ALWAYS_TRUE(TryPreserveWrapper(aGlobal
));
2910 struct CreateGlobalOptions
<nsGlobalWindow
>
2912 static MOZ_CONSTEXPR_VAR
ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind
=
2913 ProtoAndIfaceCache::WindowLike
;
2914 static MOZ_CONSTEXPR_VAR
bool ForceInitStandardClassesToFalse
= false;
2915 static void TraceGlobal(JSTracer
* aTrc
, JSObject
* aObj
);
2916 static bool PostCreateGlobal(JSContext
* aCx
, JS::Handle
<JSObject
*> aGlobal
);
2922 template <class T
, ProtoHandleGetter GetProto
>
2924 CreateGlobal(JSContext
* aCx
, T
* aNative
, nsWrapperCache
* aCache
,
2925 const JSClass
* aClass
, JS::CompartmentOptions
& aOptions
,
2926 JSPrincipals
* aPrincipal
, bool aInitStandardClasses
,
2927 JS::MutableHandle
<JSObject
*> aGlobal
)
2929 aOptions
.setTrace(CreateGlobalOptions
<T
>::TraceGlobal
);
2931 aGlobal
.set(JS_NewGlobalObject(aCx
, aClass
, aPrincipal
,
2932 JS::DontFireOnNewGlobalHook
, aOptions
));
2934 NS_WARNING("Failed to create global");
2938 JSAutoCompartment
ac(aCx
, aGlobal
);
2941 js::SetReservedSlot(aGlobal
, DOM_OBJECT_SLOT
, PRIVATE_TO_JSVAL(aNative
));
2944 aCache
->SetWrapper(aGlobal
);
2946 dom::AllocateProtoAndIfaceCache(aGlobal
,
2947 CreateGlobalOptions
<T
>::ProtoAndIfaceCacheKind
);
2949 if (!CreateGlobalOptions
<T
>::PostCreateGlobal(aCx
, aGlobal
)) {
2954 if (aInitStandardClasses
&&
2955 !CreateGlobalOptions
<T
>::ForceInitStandardClassesToFalse
&&
2956 !JS_InitStandardClasses(aCx
, aGlobal
)) {
2957 NS_WARNING("Failed to init standard classes");
2961 JS::Handle
<JSObject
*> proto
= GetProto(aCx
, aGlobal
);
2962 if (!proto
|| !JS_SplicePrototype(aCx
, aGlobal
, proto
)) {
2963 NS_WARNING("Failed to set proto");
2971 * Holds a jsid that is initialized to an interned string, with conversion to
2974 class InternedStringId
2979 InternedStringId() : id(JSID_VOID
) {}
2981 bool init(JSContext
*cx
, const char *string
) {
2982 JSString
* str
= JS_InternString(cx
, string
);
2985 id
= INTERNED_STRING_TO_JSID(cx
, str
);
2989 operator const jsid
& () {
2993 operator JS::Handle
<jsid
> () {
2994 /* This is safe because we have interned the string. */
2995 return JS::Handle
<jsid
>::fromMarkedLocation(&id
);
3000 GenericBindingGetter(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
3003 GenericBindingSetter(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
3006 GenericBindingMethod(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
3009 GenericPromiseReturningBindingMethod(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
3012 StaticMethodPromiseWrapper(JSContext
* cx
, unsigned argc
, JS::Value
* vp
);
3014 // ConvertExceptionToPromise should only be called when we have an error
3015 // condition (e.g. returned false from a JSAPI method). Note that there may be
3016 // no exception on cx, in which case this is an uncatchable failure that will
3017 // simply be propagated. Otherwise this method will attempt to convert the
3018 // exception to a Promise rejected with the exception that it will store in
3021 // promiseScope should be the scope in which the Promise should be created.
3023 ConvertExceptionToPromise(JSContext
* cx
,
3024 JSObject
* promiseScope
,
3025 JS::MutableHandle
<JS::Value
> rval
);
3027 // While we wait for the outcome of spec discussions on whether properties for
3028 // DOM global objects live on the object or the prototype, we supply this one
3029 // place to switch the behaviour, so we can easily turn this off on branches.
3031 GlobalPropertiesAreOwn()
3038 AssertReturnTypeMatchesJitinfo(const JSJitInfo
* aJitinfo
,
3039 JS::Handle
<JS::Value
> aValue
);
3042 // Returns true if aObj's global has any of the permissions named in aPermissions
3043 // set to nsIPermissionManager::ALLOW_ACTION. aPermissions must be null-terminated.
3045 CheckPermissions(JSContext
* aCx
, JSObject
* aObj
, const char* const aPermissions
[]);
3047 //Returns true if page is being prerendered.
3049 CheckSafetyInPrerendering(JSContext
* aCx
, JSObject
* aObj
);
3052 CallerSubsumes(JSObject
* aObject
);
3054 MOZ_ALWAYS_INLINE
bool
3055 CallerSubsumes(JS::Handle
<JS::Value
> aValue
)
3057 if (!aValue
.isObject()) {
3060 return CallerSubsumes(&aValue
.toObject());
3065 WrappedJSToDictionary(JSContext
* aCx
, nsISupports
* aObject
, T
& aDictionary
)
3067 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedObj
= do_QueryInterface(aObject
);
3072 JS::Rooted
<JSObject
*> obj(aCx
, wrappedObj
->GetJSObject());
3077 JSAutoCompartment
ac(aCx
, obj
);
3078 JS::Rooted
<JS::Value
> v(aCx
, JS::ObjectValue(*obj
));
3079 return aDictionary
.Init(aCx
, v
);
3084 WrappedJSToDictionary(nsISupports
* aObject
, T
& aDictionary
)
3086 nsCOMPtr
<nsIXPConnectWrappedJS
> wrappedObj
= do_QueryInterface(aObject
);
3087 NS_ENSURE_TRUE(wrappedObj
, false);
3088 JS::Rooted
<JSObject
*> obj(CycleCollectedJSRuntime::Get()->Runtime(),
3089 wrappedObj
->GetJSObject());
3090 NS_ENSURE_TRUE(obj
, false);
3092 nsIGlobalObject
* global
= xpc::NativeGlobal(obj
);
3093 NS_ENSURE_TRUE(global
, false);
3095 // we need this AutoEntryScript here because the spec requires us to execute
3096 // getters when parsing a dictionary
3097 AutoEntryScript
aes(global
);
3098 aes
.TakeOwnershipOfErrorReporting();
3100 JS::Rooted
<JS::Value
> v(aes
.cx(), JS::ObjectValue(*obj
));
3101 return aDictionary
.Init(aes
.cx(), v
);
3105 template<class T
, class S
>
3107 StrongOrRawPtr(already_AddRefed
<S
>&& aPtr
)
3109 return aPtr
.template downcast
<T
>();
3114 StrongOrRawPtr(T
* aPtr
)
3119 template<class T
, template<typename
> class SmartPtr
, class S
>
3121 StrongOrRawPtr(SmartPtr
<S
>&& aPtr
) = delete;
3125 GetErrorPrototype(JSContext
* aCx
, JS::Handle
<JSObject
*> aForObj
)
3127 return JS_GetErrorPrototype(aCx
);
3131 } // namespace mozilla
3133 #endif /* mozilla_dom_BindingUtils_h__ */