1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
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
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "jsfriendapi.h"
11 #include "AccessCheck.h"
12 #include "WrapperFactory.h"
13 #include "xpcprivate.h"
14 #include "XPCInlines.h"
15 #include "XPCQuickStubs.h"
16 #include "mozilla/dom/BindingUtils.h"
17 #include "mozilla/dom/Exceptions.h"
19 using namespace mozilla
;
22 extern const char* xpc_qsStringTable
;
24 static const xpc_qsHashEntry
*
25 LookupEntry(uint32_t tableSize
, const xpc_qsHashEntry
* table
, const nsID
& iid
)
28 const xpc_qsHashEntry
* p
;
30 i
= iid
.m0
% tableSize
;
34 if (p
->iid
.Equals(iid
))
37 } while (i
!= XPC_QS_NULL_INDEX
);
41 static const xpc_qsHashEntry
*
42 LookupInterfaceOrAncestor(uint32_t tableSize
, const xpc_qsHashEntry
* table
,
45 const xpc_qsHashEntry
* entry
= LookupEntry(tableSize
, table
, iid
);
48 * On a miss, we have to search for every interface the object
49 * supports, including ancestors.
51 nsCOMPtr
<nsIInterfaceInfo
> info
;
52 if (NS_FAILED(nsXPConnect::XPConnect()->GetInfoForIID(&iid
, getter_AddRefs(info
))))
57 nsCOMPtr
<nsIInterfaceInfo
> parent
;
58 if (NS_FAILED(info
->GetParent(getter_AddRefs(parent
))) ||
60 NS_FAILED(parent
->GetIIDShared(&piid
))) {
63 entry
= LookupEntry(tableSize
, table
, *piid
);
72 static MOZ_ALWAYS_INLINE
bool
73 HasBitInInterfacesBitmap(JSObject
* obj
, uint32_t interfaceBit
)
75 MOZ_ASSERT(IS_WN_REFLECTOR(obj
), "Not a wrapper?");
77 const XPCWrappedNativeJSClass
* clasp
=
78 (const XPCWrappedNativeJSClass
*)js::GetObjectClass(obj
);
79 return (clasp
->interfacesBitmap
& (1 << interfaceBit
)) != 0;
83 PointerFinalize(JSFreeOp
* fop
, JSObject
* obj
)
85 JSPropertyOp
* popp
= static_cast<JSPropertyOp
*>(JS_GetPrivate(obj
));
90 PointerHolderClass
= {
91 "Pointer", JSCLASS_HAS_PRIVATE
,
92 JS_PropertyStub
, JS_DeletePropertyStub
, JS_PropertyStub
, JS_StrictPropertyStub
,
93 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, PointerFinalize
97 xpc_qsDefineQuickStubs(JSContext
* cx
, JSObject
* protoArg
, unsigned flags
,
98 uint32_t ifacec
, const nsIID
** interfaces
,
99 uint32_t tableSize
, const xpc_qsHashEntry
* table
,
100 const xpc_qsPropertySpec
* propspecs
,
101 const xpc_qsFunctionSpec
* funcspecs
,
102 const char* stringTable
)
105 * Walk interfaces in reverse order to behave like XPConnect when a
106 * feature is defined in more than one of the interfaces.
108 * XPCNativeSet::FindMethod returns the first matching feature it finds,
109 * searching the interfaces forward. Here, definitions toward the
110 * front of 'interfaces' overwrite those toward the back.
112 RootedObject
proto(cx
, protoArg
);
113 for (uint32_t i
= ifacec
; i
-- != 0;) {
114 const nsID
& iid
= *interfaces
[i
];
115 const xpc_qsHashEntry
* entry
=
116 LookupInterfaceOrAncestor(tableSize
, table
, iid
);
120 // Define quick stubs for attributes.
121 const xpc_qsPropertySpec
* ps
= propspecs
+ entry
->prop_index
;
122 const xpc_qsPropertySpec
* ps_end
= ps
+ entry
->n_props
;
123 for ( ; ps
< ps_end
; ++ps
) {
124 if (!JS_DefineProperty(cx
, proto
,
125 stringTable
+ ps
->name_index
,
126 JS::UndefinedHandleValue
,
127 flags
| JSPROP_SHARED
| JSPROP_NATIVE_ACCESSORS
,
128 (JSPropertyOp
)ps
->getter
,
129 (JSStrictPropertyOp
)ps
->setter
))
133 // Define quick stubs for methods.
134 const xpc_qsFunctionSpec
* fs
= funcspecs
+ entry
->func_index
;
135 const xpc_qsFunctionSpec
* fs_end
= fs
+ entry
->n_funcs
;
136 for ( ; fs
< fs_end
; ++fs
) {
137 if (!JS_DefineFunction(cx
, proto
,
138 stringTable
+ fs
->name_index
,
139 reinterpret_cast<JSNative
>(fs
->native
),
144 if (entry
->newBindingProperties
) {
145 if (entry
->newBindingProperties
->regular
) {
146 mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx
, proto
, entry
->newBindingProperties
->regular
);
148 if (entry
->newBindingProperties
->chromeOnly
&&
149 xpc::AccessCheck::isChrome(js::GetContextCompartment(cx
))) {
150 mozilla::dom::DefineWebIDLBindingPropertiesOnXPCObject(cx
, proto
, entry
->newBindingProperties
->chromeOnly
);
154 size_t j
= entry
->parentInterface
;
155 if (j
== XPC_QS_NULL_INDEX
)
166 xpc_qsThrow(JSContext
* cx
, nsresult rv
)
168 XPCThrower::Throw(rv
, cx
);
173 * Get the interface name and member name (for error messages).
175 * We could instead have each quick stub pass its name to the error-handling
176 * functions, as that name is statically known. But that would be redundant;
177 * the information is handy at runtime anyway. Also, this code often produces
178 * a more specific error message, e.g. "[nsIDOMHTMLDocument.appendChild]"
179 * rather than "[nsIDOMNode.appendChild]".
182 GetMemberInfo(JSObject
* obj
, jsid memberId
, const char** ifaceName
)
184 *ifaceName
= "Unknown";
186 // Don't try to generate a useful name if there are security wrappers,
187 // because it isn't worth the risk of something going wrong just to generate
188 // an error message. Instead, only handle the simple case where we have the
189 // reflector in hand.
190 if (IS_WN_REFLECTOR(obj
)) {
191 XPCWrappedNative
* wrapper
= XPCWrappedNative::Get(obj
);
192 XPCWrappedNativeProto
* proto
= wrapper
->GetProto();
194 XPCNativeSet
* set
= proto
->GetSet();
196 XPCNativeMember
* member
;
197 XPCNativeInterface
* iface
;
199 if (set
->FindMember(memberId
, &member
, &iface
))
200 *ifaceName
= iface
->GetNameString();
207 GetMethodInfo(JSContext
* cx
, jsval
* vp
, const char** ifaceNamep
, jsid
* memberIdp
)
209 CallReceiver call
= CallReceiverFromVp(vp
);
210 RootedObject
funobj(cx
, &call
.callee());
211 MOZ_ASSERT(JS_ObjectIsFunction(cx
, funobj
),
212 "JSNative callee should be Function object");
213 RootedString
str(cx
, JS_GetFunctionId(JS_GetObjectFunction(funobj
)));
214 RootedId
methodId(cx
, str
? INTERNED_STRING_TO_JSID(cx
, str
) : JSID_VOID
);
215 GetMemberInfo(&call
.thisv().toObject(), methodId
, ifaceNamep
);
216 *memberIdp
= methodId
;
220 ThrowCallFailed(JSContext
* cx
, nsresult rv
,
221 const char* ifaceName
, HandleId memberId
, const char* memberName
)
223 /* Only one of memberId or memberName should be given. */
224 MOZ_ASSERT(JSID_IS_VOID(memberId
) != !memberName
);
226 // From XPCThrower::ThrowBadResult.
231 // If the cx already has a pending exception, just throw that.
233 // We used to check here to make sure the exception matched rv (whatever
234 // that means). But this meant that we'd be calling into JSAPI below with
235 // a pending exception, which isn't really kosher. The first exception thrown
236 // should generally take precedence anyway.
237 if (JS_IsExceptionPending(cx
))
242 if (!nsXPCException::NameAndFormatForNSResult(NS_ERROR_XPC_NATIVE_RETURNED_FAILURE
, nullptr, &format
) ||
247 JSAutoByteString memberNameBytes
;
249 memberName
= JSID_IS_STRING(memberId
)
250 ? memberNameBytes
.encodeLatin1(cx
, JSID_TO_STRING(memberId
))
253 if (nsXPCException::NameAndFormatForNSResult(rv
, &name
, nullptr)
255 sz
= JS_smprintf("%s 0x%x (%s) [%s.%s]",
256 format
, rv
, name
, ifaceName
, memberName
);
258 sz
= JS_smprintf("%s 0x%x [%s.%s]",
259 format
, rv
, ifaceName
, memberName
);
262 dom::Throw(cx
, rv
, sz
);
265 JS_smprintf_free(sz
);
271 xpc_qsThrowGetterSetterFailed(JSContext
* cx
, nsresult rv
, JSObject
* obj
,
274 RootedId
memberId(cx
, memberIdArg
);
275 const char* ifaceName
;
276 GetMemberInfo(obj
, memberId
, &ifaceName
);
277 return ThrowCallFailed(cx
, rv
, ifaceName
, memberId
, nullptr);
281 xpc_qsThrowGetterSetterFailed(JSContext
* cx
, nsresult rv
, JSObject
* objArg
,
282 const char* memberName
)
284 RootedObject
obj(cx
, objArg
);
285 JSString
* str
= JS_InternString(cx
, memberName
);
289 return xpc_qsThrowGetterSetterFailed(cx
, rv
, obj
,
290 INTERNED_STRING_TO_JSID(cx
, str
));
294 xpc_qsThrowGetterSetterFailed(JSContext
* cx
, nsresult rv
, JSObject
* obj
,
295 uint16_t memberIndex
)
297 return xpc_qsThrowGetterSetterFailed(cx
, rv
, obj
,
298 xpc_qsStringTable
+ memberIndex
);
302 xpc_qsThrowMethodFailed(JSContext
* cx
, nsresult rv
, jsval
* vp
)
304 const char* ifaceName
;
305 RootedId
memberId(cx
);
306 GetMethodInfo(cx
, vp
, &ifaceName
, memberId
.address());
307 return ThrowCallFailed(cx
, rv
, ifaceName
, memberId
, nullptr);
311 ThrowBadArg(JSContext
* cx
, nsresult rv
, const char* ifaceName
,
312 jsid memberId
, const char* memberName
, unsigned paramnum
)
314 /* Only one memberId or memberName should be given. */
315 MOZ_ASSERT(JSID_IS_VOID(memberId
) != !memberName
);
317 // From XPCThrower::ThrowBadParam.
321 if (!nsXPCException::NameAndFormatForNSResult(rv
, nullptr, &format
))
324 JSAutoByteString memberNameBytes
;
326 memberName
= JSID_IS_STRING(memberId
)
327 ? memberNameBytes
.encodeLatin1(cx
, JSID_TO_STRING(memberId
))
330 sz
= JS_smprintf("%s arg %u [%s.%s]",
331 format
, (unsigned int) paramnum
, ifaceName
, memberName
);
333 dom::Throw(cx
, rv
, sz
);
336 JS_smprintf_free(sz
);
340 xpc_qsThrowBadArg(JSContext
* cx
, nsresult rv
, jsval
* vp
, unsigned paramnum
)
342 const char* ifaceName
;
343 RootedId
memberId(cx
);
344 GetMethodInfo(cx
, vp
, &ifaceName
, memberId
.address());
345 ThrowBadArg(cx
, rv
, ifaceName
, memberId
, nullptr, paramnum
);
349 xpc_qsThrowBadArgWithCcx(XPCCallContext
& ccx
, nsresult rv
, unsigned paramnum
)
351 XPCThrower::ThrowBadParam(rv
, paramnum
, ccx
);
355 xpc_qsThrowBadArgWithDetails(JSContext
* cx
, nsresult rv
, unsigned paramnum
,
356 const char* ifaceName
, const char* memberName
)
358 ThrowBadArg(cx
, rv
, ifaceName
, JSID_VOID
, memberName
, paramnum
);
362 xpc_qsThrowBadSetterValue(JSContext
* cx
, nsresult rv
,
363 JSObject
* obj
, jsid propIdArg
)
365 RootedId
propId(cx
, propIdArg
);
366 const char* ifaceName
;
367 GetMemberInfo(obj
, propId
, &ifaceName
);
368 ThrowBadArg(cx
, rv
, ifaceName
, propId
, nullptr, 0);
372 xpc_qsThrowBadSetterValue(JSContext
* cx
, nsresult rv
,
373 JSObject
* objArg
, const char* propName
)
375 RootedObject
obj(cx
, objArg
);
376 JSString
* str
= JS_InternString(cx
, propName
);
380 xpc_qsThrowBadSetterValue(cx
, rv
, obj
, INTERNED_STRING_TO_JSID(cx
, str
));
384 xpc_qsThrowBadSetterValue(JSContext
* cx
, nsresult rv
, JSObject
* obj
,
387 xpc_qsThrowBadSetterValue(cx
, rv
, obj
, xpc_qsStringTable
+ name_index
);
391 xpc_qsGetterOnlyPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, bool strict
,
392 MutableHandleValue vp
)
394 return JS_ReportErrorFlagsAndNumber(cx
,
395 JSREPORT_WARNING
| JSREPORT_STRICT
|
396 JSREPORT_STRICT_MODE_ERROR
,
397 js_GetErrorMessage
, nullptr,
402 xpc_qsGetterOnlyNativeStub(JSContext
* cx
, unsigned argc
, jsval
* vp
)
404 return JS_ReportErrorFlagsAndNumber(cx
,
405 JSREPORT_WARNING
| JSREPORT_STRICT
|
406 JSREPORT_STRICT_MODE_ERROR
,
407 js_GetErrorMessage
, nullptr,
411 xpc_qsDOMString::xpc_qsDOMString(JSContext
* cx
, HandleValue v
,
412 MutableHandleValue pval
, bool notpassed
,
413 StringificationBehavior nullBehavior
,
414 StringificationBehavior undefinedBehavior
)
416 typedef implementation_type::char_traits traits
;
417 // From the T_DOMSTRING case in XPCConvert::JSData2Native.
418 JSString
* s
= InitOrStringify
<traits
>(cx
, v
,
425 nsAutoString
* str
= new(mBuf
) implementation_type();
427 mValid
= AssignJSString(cx
, *str
, s
);
430 xpc_qsACString::xpc_qsACString(JSContext
* cx
, HandleValue v
,
431 MutableHandleValue pval
, bool notpassed
,
432 StringificationBehavior nullBehavior
,
433 StringificationBehavior undefinedBehavior
)
435 typedef implementation_type::char_traits traits
;
436 // From the T_CSTRING case in XPCConvert::JSData2Native.
437 JSString
* s
= InitOrStringify
<traits
>(cx
, v
,
444 size_t len
= JS_GetStringEncodingLength(cx
, s
);
445 if (len
== size_t(-1)) {
450 JSAutoByteString
bytes(cx
, s
);
456 new(mBuf
) implementation_type(bytes
.ptr(), len
);
460 xpc_qsAUTF8String::xpc_qsAUTF8String(JSContext
* cx
, HandleValue v
, MutableHandleValue pval
, bool notpassed
)
462 typedef nsCharTraits
<char16_t
> traits
;
463 // From the T_UTF8STRING case in XPCConvert::JSData2Native.
464 JSString
* s
= InitOrStringify
<traits
>(cx
, v
, pval
, notpassed
, eNull
, eNull
);
469 if (!str
.init(cx
, s
)) {
474 new(mBuf
) implementation_type(str
);
479 getNative(nsISupports
* idobj
,
483 nsISupports
** pThisRef
,
486 nsresult rv
= idobj
->QueryInterface(iid
, ppThis
);
487 *pThisRef
= static_cast<nsISupports
*>(*ppThis
);
488 if (NS_SUCCEEDED(rv
))
489 *vp
= OBJECT_TO_JSVAL(obj
);
493 static inline nsresult
494 getNativeFromWrapper(JSContext
* cx
,
495 XPCWrappedNative
* wrapper
,
498 nsISupports
** pThisRef
,
501 RootedObject
obj(cx
, wrapper
->GetFlatJSObject());
502 return getNative(wrapper
->GetIdentityObject(), obj
, iid
, ppThis
, pThisRef
,
508 getWrapper(JSContext
* cx
,
510 XPCWrappedNative
** wrapper
,
512 XPCWrappedNativeTearOff
** tearoff
)
514 // We can have at most three layers in need of unwrapping here:
515 // * A (possible) security wrapper
516 // * A (possible) Xray waiver
517 // * A (possible) outer window
519 // If we pass stopAtOuter == false, we can handle all three with one call
520 // to js::CheckedUnwrap.
521 if (js::IsWrapper(obj
)) {
522 JSObject
* inner
= js::CheckedUnwrap(obj
, /* stopAtOuter = */ false);
524 // The safe unwrap might have failed if we encountered an object that
525 // we're not allowed to unwrap. If it didn't fail though, we should be
526 // done with wrappers.
528 return NS_ERROR_XPC_SECURITY_MANAGER_VETO
;
529 MOZ_ASSERT(!js::IsWrapper(inner
));
534 // Start with sane values.
539 if (dom::IsDOMObject(obj
)) {
547 // If |obj| is of the tearoff class, that means we're dealing with a JS
548 // object reflection of a particular interface (ie, |foo.nsIBar|). These
549 // JS objects are parented to their wrapper, so we snag the tearoff object
550 // along the way (if desired), and then set |obj| to its parent.
551 const js::Class
* clasp
= js::GetObjectClass(obj
);
552 if (clasp
== &XPC_WN_Tearoff_JSClass
) {
553 *tearoff
= (XPCWrappedNativeTearOff
*) js::GetObjectPrivate(obj
);
554 obj
= js::GetObjectParent(obj
);
557 // If we've got a WN, store things the way callers expect. Otherwise, leave
558 // things null and return.
559 if (IS_WN_CLASS(clasp
))
560 *wrapper
= XPCWrappedNative::Get(obj
);
566 castNative(JSContext
* cx
,
567 XPCWrappedNative
* wrapper
,
569 XPCWrappedNativeTearOff
* tearoff
,
572 nsISupports
** pThisRef
,
573 MutableHandleValue vp
)
575 RootedObject
cur(cx
, curArg
);
577 nsresult rv
= getNativeFromWrapper(cx
,wrapper
, iid
, ppThis
, pThisRef
,
580 if (rv
!= NS_ERROR_NO_INTERFACE
)
584 if (!(native
= mozilla::dom::UnwrapDOMObjectToISupports(cur
))) {
586 return NS_ERROR_ILLEGAL_VALUE
;
589 if (NS_SUCCEEDED(getNative(native
, cur
, iid
, ppThis
, pThisRef
, vp
.address()))) {
595 return NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
;
599 castNativeFromWrapper(JSContext
* cx
,
601 uint32_t interfaceBit
,
605 MutableHandleValue pVal
,
608 XPCWrappedNative
* wrapper
;
609 XPCWrappedNativeTearOff
* tearoff
;
612 if (IS_WN_REFLECTOR(obj
)) {
614 wrapper
= XPCWrappedNative::Get(obj
);
617 *rv
= getWrapper(cx
, obj
, &wrapper
, &cur
, &tearoff
);
624 native
= wrapper
->GetIdentityObject();
625 cur
= wrapper
->GetFlatJSObject();
626 if (!native
|| !HasBitInInterfacesBitmap(cur
, interfaceBit
)) {
629 } else if (cur
&& protoDepth
>= 0) {
630 const mozilla::dom::DOMJSClass
* domClass
=
631 mozilla::dom::GetDOMClass(cur
);
632 native
= mozilla::dom::UnwrapDOMObject
<nsISupports
>(cur
);
634 (uint32_t)domClass
->mInterfaceChain
[protoDepth
] != protoID
) {
643 pVal
.setObjectOrNull(cur
);
646 *rv
= NS_ERROR_XPC_BAD_CONVERT_JS
;
653 xpc_qsUnwrapArgImpl(JSContext
* cx
,
657 nsISupports
** ppArgRef
,
658 MutableHandleValue vp
)
661 RootedObject
src(cx
, xpc_qsUnwrapObj(v
, ppArgRef
, &rv
));
668 XPCWrappedNative
* wrapper
;
669 XPCWrappedNativeTearOff
* tearoff
;
671 rv
= getWrapper(cx
, src
, &wrapper
, &obj2
, &tearoff
);
672 NS_ENSURE_SUCCESS(rv
, rv
);
674 if (wrapper
|| obj2
) {
675 if (NS_FAILED(castNative(cx
, wrapper
, obj2
, tearoff
, iid
, ppArg
,
677 return NS_ERROR_XPC_BAD_CONVERT_JS
;
683 // Try to unwrap a slim wrapper.
685 if (XPCConvert::GetISupportsFromJSObject(src
, &iface
)) {
686 if (!iface
|| NS_FAILED(iface
->QueryInterface(iid
, ppArg
))) {
688 return NS_ERROR_XPC_BAD_CONVERT_JS
;
691 *ppArgRef
= static_cast<nsISupports
*>(*ppArg
);
695 // Create the ccx needed for quick stubs.
696 XPCCallContext
ccx(JS_CALLER
, cx
);
697 if (!ccx
.IsValid()) {
699 return NS_ERROR_XPC_BAD_CONVERT_JS
;
702 nsRefPtr
<nsXPCWrappedJS
> wrappedJS
;
703 rv
= nsXPCWrappedJS::GetNewOrUsed(src
, iid
, getter_AddRefs(wrappedJS
));
704 if (NS_FAILED(rv
) || !wrappedJS
) {
709 // We need to go through the QueryInterface logic to make this return
710 // the right thing for the various 'special' interfaces; e.g.
711 // nsIPropertyBag. We must use AggregatedQueryInterface in cases where
712 // there is an outer to avoid nasty recursion.
713 rv
= wrappedJS
->QueryInterface(iid
, ppArg
);
714 if (NS_SUCCEEDED(rv
)) {
715 *ppArgRef
= static_cast<nsISupports
*>(*ppArg
);
716 vp
.setObjectOrNull(wrappedJS
->GetJSObject());
722 xpc_qsJsvalToCharStr(JSContext
* cx
, HandleValue v
, JSAutoByteString
* bytes
)
724 MOZ_ASSERT(!bytes
->ptr());
726 if (v
.isNullOrUndefined())
729 JSString
* str
= ToString(cx
, v
);
732 return !!bytes
->encodeLatin1(cx
, str
);
738 NonVoidStringToJsval(JSContext
* cx
, nsAString
& str
, MutableHandleValue rval
)
740 nsStringBuffer
* sharedBuffer
;
741 if (!XPCStringConvert::ReadableToJSVal(cx
, str
, &sharedBuffer
, rval
))
745 // The string was shared but ReadableToJSVal didn't addref it.
746 // Move the ownership from str to jsstr.
747 str
.ForgetSharedBuffer();
755 xpc_qsXPCOMObjectToJsval(JSContext
* cx
, qsObjectHelper
& aHelper
,
756 const nsIID
* iid
, XPCNativeInterface
** iface
,
757 MutableHandleValue rval
)
759 NS_PRECONDITION(iface
, "Who did that and why?");
761 // From the T_INTERFACE case in XPCConvert::NativeData2JS.
762 // This is one of the slowest things quick stubs do.
765 if (!XPCConvert::NativeInterface2JSObject(rval
, nullptr,
768 // I can't tell if NativeInterface2JSObject throws JS exceptions
769 // or not. This is a sloppy stab at the right semantics; the
770 // method really ought to be fixed to behave consistently.
771 if (!JS_IsExceptionPending(cx
))
772 xpc_qsThrow(cx
, NS_FAILED(rv
) ? rv
: NS_ERROR_UNEXPECTED
);
777 JSObject
* jsobj
= rval
.toObjectOrNull();
778 if (jsobj
&& !js::GetObjectParent(jsobj
))
779 MOZ_ASSERT(js::GetObjectClass(jsobj
)->flags
& JSCLASS_IS_GLOBAL
,
780 "Why did we recreate this wrapper?");
787 xpc_qsVariantToJsval(JSContext
* aCx
,
789 MutableHandleValue rval
)
791 // From the T_INTERFACE case in XPCConvert::NativeData2JS.
792 // Error handling is in XPCWrappedNative::CallMethod.
795 bool ok
= XPCVariant::VariantDataToJS(p
, &rv
, rval
);
797 xpc_qsThrow(aCx
, rv
);
806 xpc_qsAssertContextOK(JSContext
* cx
)
808 XPCJSContextStack
* stack
= XPCJSRuntime::Get()->GetJSContextStack();
810 JSContext
* topJSContext
= stack
->Peek();
812 // This is what we're actually trying to assert here.
813 MOZ_ASSERT(cx
== topJSContext
, "wrong context on XPCJSContextStack!");